HYSBZ - 1026 windy数 (数位DP)

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24269

代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

using namespace std;

int dp[15][10];
int ans;
int bit[15];

void init()
{
    memset(dp,0,sizeof(dp));

    for(int i=0;i<=9;i++)
    {
        dp[1][i]=1;
    }

    for(int i=2;i<=10;i++)
    {
        for(int j=0;j<=9;j++)
        {
            for(int k=0;k<=9;k++)
            {
                if(abs(j-k)>=2)
                    dp[i][j]=dp[i][j]+dp[i-1][k];
            }
        }
    }
    /*for(int i=1;i<=3;i++)
    {
        for(int j=0;j<=9;j++)
        {
            printf("%d ",dp[i][j]);
        }
        printf("\n");
    }*/
}

int solve(int x)                     //  321
{
    ans=0;
    memset(bit,0,sizeof(bit));
    int len=0;
    while(x)
    {
        bit[++len]=x%10;
        x=x/10;
    }
    bit[len+1]=0;

    for(int i=1;i<len;i++)         //   1-99
    {
        for(int j=1;j<=9;j++)
        {
            ans=ans+dp[i][j];
            //printf("%d\n",dp[i][j]);
        }
    }
    //printf("%d\n",ans);
    for(int i=1;i<bit[len];i++)    //    100-300
    {
        ans=ans+dp[len][i];
    }
    //printf("%d\n",ans);
    for(int i=len-1;i>=0;i--)      //    301-321
    {
        for(int j=0;j<bit[i];j++)
        {
            if(abs(j-bit[i+1])>=2)
                ans=ans+dp[i][j];
        }
        if(abs(bit[i]-bit[i+1])<2)
            break;
    }
    //printf("%d\n",ans);
    return ans;
}

int main()
{
    init();
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        printf("%d\n",solve(m+1)-solve(n));
    }
}

数位DP的大体思路:

用预处理一个表,从这个表中找答案。

dp【2】【3】表示30到39之间满足题意的数即 30 31 35 36 37 38 39.

dp【3】【2】表示200-300之间满足题意的数。


现在想求321到1之间的满足的题意的数。


找1-99   100-300 301-321 相加。



还有就是为什么m+1.不太懂呀。

1 2 3 4 5 6 7 8 9 10



学习数位DP时的代码。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

using namespace std;

int dp[15][10];

void init()
{
    memset(dp,0,sizeof(dp));
    for(int i=0;i<=9;i++)
    {
        dp[1][i]=1;
    }

    for(int i=2;i<=10;i++)
    {
        for(int j=0;j<10;j++)        //   首位
        {
            for(int k=0;k<10;k++)    //   首位的下一位
            {
                if(abs(j-k)>=2)
                    dp[i][j]=dp[i][j]+dp[i-1][k];
            }
        }
    }
}
int a[5];

int judge(int x)
{
    int k=x;
    int i=0;
    while(k)
    {
        a[i++]=k%10;
        k=k/10;
    }
    //printf("%d %d %d ",a[0],a[1],a[2]);
    if(abs(a[0]-a[1])>=2&&abs(a[1]-a[2])>=2)
        return 1;
    else return 0;

}
int main()
{

    init();

    for(int i=1;i<10;i++)
    {
        for(int j=0;j<10;j++)
        {
            printf("%d ",dp[i][j]);
        }
        printf("\n");
    }

    for(int i=900;i<=999;i++)
    {
        if(judge(i))
            printf("%d ",i);
        if(i%10==0)
            printf("\n");
    }
}


你可能感兴趣的:(HYSBZ - 1026 windy数 (数位DP))