HDU-2332 机器人的舞蹈 递推
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2232
直接進入正題,這題要求解的是一個條件極其寬松下的組合題,似乎在看見這題的時候,我們就能遇見這道題的答案會是多么的龐大,所以題中也才會有 % 9937 這樣的提示。對于如此大的一個運算,只走一步的話還好辦,有9種情況,(順時針和逆時針旋轉2次加上相鄰兩個交換位置(交換一對的4次,交換兩對的2次)最后加上原地不動的1次),就1次就夠麻煩的,計算結果表明,兩步共有633種可能, 足以見得后面的情況是多么的復雜。
各種百度后,我接受了接下來說明的好的方法。保留一定量的信息,通過遞推求得,再在這些信息上求解這個問題。保留的信息為每個機器人在第N次行走后到達各個位置的方案數。提出了這個初步的計劃后,我們應該能想到,這個方法的目的就是使得四個人行走的方格變得更加的干凈,我們先一個一個機器人來計算它的特性。
假設布局如下(上面依次站著A, B, C, D號機器人):
"0"?-a??? "1" -b
"2"?-c?? ?"3" -d
那么對于剛開始位于 "0" 的 A 機器人來說,此時它位于 "0" 的方案數為 1, 位于其他三個區域的方案數為 0,這是顯而易見的,那么下一時刻呢?是這樣的,此時位于"0"的方案數就變成了 1,位于"1"的方案數為 1,位于"2"的方案數為 1, 位于"3"的方案數為 0。哦,原來是這樣的,就是每次加上跟 "x" 位置相鄰以及本身位置上一步的方案數。
有: dp[N][0] = dp[N-1][0] + dp[N-1][1] + dp[N-1][2];?? //?原諒我變量名取了dp,它看起來確實比較順眼
dp[N][1] = dp[N-1][0] + dp[N-1][1] + dp[N-1][3];
dp[N][2] = dp[N-1][0] + dp[N-1][2] + dp[N-1][3];
dp[N][3] = dp[N-1][1] + dp[N-1][2] + dp[N-1][3];
再對初始化位置為 "1", "2", "3" 的機器人進相同的步驟就能夠計算出每個機器人在第N步時,在每一個區域的方案總數。
做好了上面的準備工作,我們就能夠利用這些信息來進一步解決這個棘手的問題。那么我們還是來看最簡單的只走一步來分析它,由于我們已經知道了走了1步后,各個機器人最后在四個位置的方案數有多少種。
好,我們開始來數,首先是順時針旋轉,此時 A 到達了 "1", B到達了 "3", C到達了 "0" , D到達了 "2",恩,這個情況出現了,于是我們要去找了,到第 N = 1 步的數據中尋找A在"1"有多少種方案,依次 N =?1時 B在"3",C在"0",D在"2"的方案數。將他們相乘即得到這種終態下的方案數。接下來就是剩下8種狀態對應的方案數了。在N = 1步中這些方案總數都是1種。
但是新的問題又出來了,難道我要把每一步的所有可能的情況都推算出來嗎,其實這里有個蠻力的法子,就是把所有可能的終態都計算一遍,大不了就是多加幾個零唄。我們可以推算出終態總數為24種,也即4!。
這樣分析完之后,題目就有可解性了。動手吧。
代碼如下:
View Code 1 #include <cstdio>2 #include <cstdlib>
3 #include <cmath>
4 #include <cstring>
5 #include <iostream>
6 #include <algorithm>
7 using namespace std;
8
9 struct Statu
10 {
11 int dp[105][4];
12 }A[4]; // 四個機器人的位置信息
13
14 void deal( void )
15 {
16 for( int i = 0; i < 4; ++i )
17 {
18 for( int j = 1; j <= 100; ++j )
19 {
20 A[i].dp[j][0] = ( A[i].dp[j-1][0] + A[i].dp[j-1][1] + A[i].dp[j-1][2] ) % 9937;
21 A[i].dp[j][1] = ( A[i].dp[j-1][0] + A[i].dp[j-1][1] + A[i].dp[j-1][3] ) % 9937;
22 A[i].dp[j][2] = ( A[i].dp[j-1][0] + A[i].dp[j-1][2] + A[i].dp[j-1][3] ) % 9937;
23 A[i].dp[j][3] = ( A[i].dp[j-1][1] + A[i].dp[j-1][2] + A[i].dp[j-1][3] ) % 9937;
24 }
25 }
26 }
27
28 int slove( int N )
29 {
30 int sum = 0, t, base[4] = { 0, 1, 2, 3 };
31 for( int i = 0; i < 24; ++i )
32 {
33 t = ( A[0].dp[N][ base[0] ] % 9937 ) * ( A[1].dp[N][ base[1] ] % 9937 );
34 t %= 9937;
35 t *= ( A[2].dp[N][ base[2] ] % 9937 );
36 t %= 9937;
37 t *= ( A[3].dp[N][ base[3] ] % 9937 );
38 sum = ( sum + t ) % 9937;
39 next_permutation( base, base + 4 );
40 }
41 return sum;
42 }
43
44 int main()
45 {
46 for( int i = 0; i < 4; ++i )
47 {
48 A[i].dp[0][i] = 1;
49 }
50
51 deal();
52
53 int N;
54 while( scanf( "%d", &N ) != EOF )
55 {
56 printf( "%d\n", slove( N ) );
57 }
58
59 return 0;
60 }
總結
以上是生活随笔為你收集整理的HDU-2332 机器人的舞蹈 递推的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有限状态机的C++实现(2)-bayon
- 下一篇: 【致青春】致成长路上的那些琐事