数位DP bzoj1026

1026: [SCOI2009]windy数

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 5809  Solved: 2589
[Submit][Status][Discuss]

Description

  windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?

Input

  包含两个整数,A B。

Output

  一个整数

Sample Input

【输入样例一】
1 10
【输入样例二】
25 50

Sample Output

【输出样例一】
9
【输出样例二】
20

HINT

【数据规模和约定】

100%的数据,满足 1 <= A <= B <= 2000000000 。

代码:

 1 /*
 2 与上两道题类似,但不同的是本题要考虑首位非0。
 3 */
 4 #include<iostream>
 5 #include<string>
 6 #include<cstdio>
 7 #include<cmath>
 8 #include<cstring>
 9 #include<algorithm>
10 #include<vector>
11 #include<iomanip>
12 #include<queue>
13 #include<stack>
14 using namespace std;
15 int n,m;
16 int dp[13][10];
17 void init()
18 {
19     for(int i=0;i<10;i++)  //小于十的数单独计算
20     {
21         dp[1][i]=1;
22     }
23     for(int i=2;i<11;i++)
24     {
25         for(int j=0;j<10;j++)
26         {
27             for(int k=0;k<10;k++)
28             {
29                 if(abs(j-k)>=2)
30                 dp[i][j]+=dp[i-1][k];
31             }
32         }
33     }
34 }
35 int insum(int n)
36 {
37     int sum=0;
38     int cnt=0;
39     int c[13]={0};
40     while(n)
41     {
42         c[++cnt]=n%10;
43         n=n/10;
44     }
45     c[cnt+1]=0;
46     for(int i=1;i<cnt;i++)  //算前cnt-1位
47     {
48         for(int j=1;j<10;j++)   //j从1开始,前导非0
49         {
50             sum+=dp[i][j];
51         }
52     }
53     for(int i=1;i<c[cnt];i++)  //算最高位
54     {
55         sum+=dp[cnt][i];
56     }
57     for(int i=cnt-1;i>0;i--)  //最高位位已经算过了,从cnt-1位开始算
58     {
59         for(int j=0;j<c[i];j++)
60         {
61             if(abs(j-c[i+1])>=2)
62             sum+=dp[i][j];
63         }
64         if(abs(c[i]-c[i+1])<2)
65         break;
66     }
67     return sum;
68 }
69 int main()
70 {
71     while(cin>>n>>m)
72     {
73         memset(dp,0,sizeof(dp));
74         init();
75         cout<<insum(m+1)-insum(n)<<endl;
76     }
77     return 0;
78 }
原文地址:https://www.cnblogs.com/--ZHIYUAN/p/5758073.html