HDU 2154 跳舞毯 | DP | 递推 | 规律

 

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

 

 

posted @ 2017-10-03 17:13  kimsimple  阅读(280)  评论(0编辑  收藏  举报