bzoj:1026: [SCOI2009]windy数(数位dp)

1026: [SCOI2009]windy数

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 7982  Solved: 3593

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 。

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 
 5 using namespace std;
 6 int f[15][15],a[15];
 7 
 8 void init()
 9 {
10     for (int i=0; i<=9; ++i)
11         f[1][i] = 1;
12     for (int i=2; i<=10; ++i)
13         for (int j=0; j<=9; ++j)
14             for (int k=0; k<=9; ++k)
15                 if (abs(j-k)>=2) f[i][j] += f[i-1][k];//相邻两位数满足>=2 
16 }
17 int calc(int x)//计算小于等于x的windy数的个数 
18 {
19     if (!x) return 0;
20     int tot = 0,ret = 0;
21     while (x)
22     {
23         a[++tot] = x%10;
24         x /= 10;
25     }
26     for (int i=tot; i; --i)//枚举位数 
27     {
28         if (tot-i>=2&&abs(a[i+1]-a[i+2])<=1) break;//不满足相邻两位数>=2的条件 
29         for (int j=0+(i==tot); j<a[i]+(i==1); ++j)
30             if (i==tot||abs(j-a[i+1])>=2) ret += f[i][j];
31     }
32     for (int i=tot-1; i; --i)
33         for (int j=1; j<=9; ++j)
34             ret += f[i][j];
35     return ret;
36 }
37 int main()
38 {
39     int n,m;
40     init();
41     while (scanf("%d%d",&n,&m)!=EOF)
42     {
43         printf("%d
",calc(m)-calc(n-1));
44     }
45     return 0;
46 }
原文地址:https://www.cnblogs.com/mjtcn/p/7367594.html