• 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
    ",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
    ",dp[n][1]);
        }
        return 0;
    }

    参考:http://www.voidcn.com/article/p-pkzamxse-et.html

  • 相关阅读:
    OAuth客户端调用
    OAuth中client id的处理
    Task作为返回值以及Task<TResult>作为返回值
    Netscaler立身之本—NAT
    Citrix Netscaler负载均衡算法
    Netscaler重置密码的方法
    Netscaler的超高端口复用助力应对公网地址紧张
    Netscaler工作流程
    深入理解Netscaler INat
    Citrix Netscaler版本管理和选择
  • 原文地址:https://www.cnblogs.com/kimsimple/p/7623934.html
Copyright © 2020-2023  润新知