HDU 2154 跳舞毯 | DP | 遞推 | 規律
阿新 • • 發佈:2017-10-03
輸入 tom bcb win stream stl 也有 輸出 由於
小黑買來一塊圓形的毯子,把它們分成三等分,分別標上A,B,C,稱之為“跳舞毯”,他的運動方式是每次都從A開始跳,每次都可以任意跳到其他塊,但最後必須跳回A,且不能原地跳.為達到減肥效果,小黑每天都會堅持跳n次,有天他突然想知道當他跳n次時共幾種跳法,結果想了好幾天沒想出來-_-
現在就請你幫幫他,算出總共有多少跳法。
當n為0時輸入結束。
每個測試用例的輸出占一行,由於跳法非常多,輸出其對10000取模的結果.
Description
由於長期缺乏運動,小黑發現自己的身材臃腫了許多,於是他想健身,更準確地說是減肥。小黑買來一塊圓形的毯子,把它們分成三等分,分別標上A,B,C,稱之為“跳舞毯”,他的運動方式是每次都從A開始跳,每次都可以任意跳到其他塊,但最後必須跳回A,且不能原地跳.為達到減肥效果,小黑每天都會堅持跳n次,有天他突然想知道當他跳n次時共幾種跳法,結果想了好幾天沒想出來-_-
現在就請你幫幫他,算出總共有多少跳法。
Input
測試輸入包含若幹測試用例。每個測試用例占一行,表示n的值(1<=n<=1000)。當n為0時輸入結束。
Output
Sample Input
2 3 4 0Sample Output
2 2 6 1.DFS得出結果,找規律
#include <iostream> #include "cstdio" using namespace std; #define MOD 10000 int n,cnt; int dfs(char c,int k) { if(k==n+1) { if(c==‘A‘) cnt++; return cnt%MOD; } if(c==‘A‘){ dfs(‘B‘,k+1); dfs(‘C‘,k+1); } else if(c==‘B‘){ dfs(‘A‘,k+1); dfs(‘C‘,k+1); } else if(c==‘C‘){ dfs(‘B‘,k+1); dfs(‘A‘,k+1); } } int main() { //freopen("out.txt","w",stdout);int ans=0; for(n=2;n<20;n++){ cnt=0; cout<<n<<" "<<dfs(‘A‘,1)<<endl; } return 0; }
4 6 5 10 6 22 7 42 8 86 9 170 10 342 11 682 12 1366 13 2730 14 5462 15 922 16 1846 17 3690 18 7382 19 4762
觀察數據找到規律:
if(i%2==0)
a[i]=2*a[i-1]+2;
else a[i]=2*a[i-1]-2;
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int main() { int i,n,step[1008]={0,0,2,2}; for(i=4; i<1002; i++)//打表 { if(i%2==0) step[i]=2*step[i-1]+2; else step[i]=2*step[i-1]-2; step[i]=step[i]%10000; } while(scanf("%d",&n)&&n!=0) { printf("%d\n",step[n]%10000); } return 0; }
參考:http://blog.csdn.net/castledrv/article/details/46897311
2.遞推式f[i]=2^(i-1)-f[i-1] 進一步推出f[i]=2^(i-2)+f[i-2]
含義:
A_A B | C 2
A__A BC | CB 2
A___A BAB | CAC | BCB | CBC | BAC | CAB 2
即後四個空全排列-以A結尾的排列數
f[i]=2^(i-1)-f[i-1]
f[i-1]=2^(i-2)-f[i-2]
->
f[i]=2^(i-2)+f[i-2]
#include<iostream> using namespace std; #define mod 10000 int main() { int a[1600] = { 0,0,2,2 }; int n; int k = 4; for (int i = 4; i < 1001; i++)///打表 { a[i] = (k%mod + a[i - 2] % mod) % mod; k = k * 2 % mod; } while (cin >> n&&n) { cout << a[n] << endl; } return 0; }
參考:http://www.cnblogs.com/dream-wind/archive/2012/03/16/2400596.html
3.DP
dp[i][j]
j=1表示第i步紅色的步數
j=2表示第i步在黃色的步數
j=3表示第i步在藍色的步數
對於每次跳到紅色的狀態有:第i-1必須是在藍色和黃色的地板上
所以dp[i][1]=dp[i-1][2]+dp[i-1][3];
第i步黃色也有dp[i][2]=dp[i-1][1]+dp[i-1][3];
第i步藍色有dp[i][3]=dp[i-1][1]+dp[i-1][2];
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; int dp[1001][3]; int main() { dp[1][2]=1;int i; dp[1][3]=1;dp[1][1]=0; for(i=2;i<=1000;i++) { dp[i][1]=dp[i-1][2]+dp[i-1][3]; dp[i][2]=dp[i-1][1]+dp[i-1][3]; dp[i][3]=dp[i-1][1]+dp[i-1][2]; dp[i][1]=dp[i][1]%10000; dp[i][2]=dp[i][2]%10000; dp[i][3]=dp[i][3]%10000; } int n; while(scanf("%d",&n)&&n) { printf("%d\n",dp[n][1]); } return 0; }
參考:http://www.voidcn.com/article/p-pkzamxse-et.html
HDU 2154 跳舞毯 | DP | 遞推 | 規律