数位DP——UESTC1307 windy数

来源:互联网 发布:分布式的文档数据库是 编辑:程序博客网 时间:2024/05/23 01:24

题目链接:

http://acm.uestc.edu.cn/problem.php?pid=1307


题目大意:

windy数的定义:相邻的两数之差大于等于2且不含前导0。

给定一个闭区间n--m,求取该区间中共有多少个windy数。


解题思路:

基础的数位DP

dp[11][10]:共i位数的时候最高位为j时windy数的个数


源代码:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<set>#include<map>#include<vector>#include<algorithm>#define INF 0x3f3f3f3fusing namespace std;//windy数,相邻数字之差大于等于2//只有1位的数字都是windy数int dp[11][10];     //共i位且最高位是j,windy数字的个数int date[11];int n,m;void init()         //初始化dp数组{    int i,j,k,t;    memset(dp,0,sizeof(dp));    for(i=0; i<=9; i++)        dp[1][i]=1;    for(i=2; i<=10; i++)        //枚举位数    {        for(j=0; j<=9; j++)     //枚举第i位        {            for(k=0; k<=9; k++) //枚举第i-1位            {                if(abs(j-k)>=2)                    dp[i][j]+=dp[i-1][k];            }            //printf("%d\n",dp[i][j]);        }    }    return;}int DP(int x){    int i,j,k,t,len,ans;    ans=len=0;    while(x)    {        date[++len]=x%10;        x/=10;    }    //首先求出len-1位到1位windy数的个数    for(i=1; i<len; i++)    {        for(j=1; j<=9; j++)            ans+=dp[i][j];    }    //求取len位windy数的个数    //枚举最高位的值,i不能取0,也不能去date[len]    for(i=1; i<date[len]; i++)    {        ans+=dp[len][i];    }    //最高为取date[len]时    for(i=len-1; i>=1; i--)    {        for(j=0; j<date[i]; j++)    //注意这个地方j是从0开始的        {            if(abs(j-date[i+1])>=2)                ans+=dp[i][j];        }        //如果在前面的边界中出现非法,直接退出        if(abs(date[i]-date[i+1])<2)            break;    }    return ans;}int main(){    //freopen("in.txt","r",stdin);    init();    while(scanf("%d%d",&n,&m)==2)    {        printf("%d\n",DP(m+1)-DP(n));    }    return 0;}