1. 程式人生 > >HDU 2154 跳舞毯 | DP | 遞推 | 規律

HDU 2154 跳舞毯 | DP | 遞推 | 規律

輸入 tom bcb win stream stl 也有 輸出 由於

Description

由於長期缺乏運動,小黑發現自己的身材臃腫了許多,於是他想健身,更準確地說是減肥。
小黑買來一塊圓形的毯子,把它們分成三等分,分別標上A,B,C,稱之為“跳舞毯”,他的運動方式是每次都從A開始跳,每次都可以任意跳到其他塊,但最後必須跳回A,且不能原地跳.為達到減肥效果,小黑每天都會堅持跳n次,有天他突然想知道當他跳n次時共幾種跳法,結果想了好幾天沒想出來-_-
現在就請你幫幫他,算出總共有多少跳法。
技術分享

Input

測試輸入包含若幹測試用例。每個測試用例占一行,表示n的值(1<=n<=1000)。
當n為0時輸入結束。

Output

每個測試用例的輸出占一行,由於跳法非常多,輸出其對10000取模的結果.

Sample Input

2 3 4 0

Sample 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 | 遞推 | 規律