题目背景
windy 定义了一种 windy 数。
题目描述
不含前导零且相邻两个数字之差至少为 22 的正整数被称为 windy 数。windy 想知道,在 aa和 bb 之间,包括 aa 和 bb ,总共有多少个 windy 数?
输入格式
输入只有一行两个整数,分别表示 aa 和 bb。
输出格式
输出一行一个整数表示答案。
输入输出样例
输入 #1复制
1 10
输出 #1复制
9
输入 #2复制
25 50
输出 #2复制
20
参考https://www.luogu.com.cn/blog/HONOUR/solution-p2657
从0开始数位dp。
#include <bits/stdc++.h>
using namespace std;
int a, b, num[33], len;
int dp[33][33][2][2];
int dfs(int len, int last, int flag, int zero) {//参数为从高到低当前处理到第几位 范围是1到len last是上一位的数 flag表示之前的部分是否紧贴边界 zero表示是否有前导0
if(len == 0) return 1;//实际上可以在下面代码中特判 比如len == 1且满足条件 则直接ans += 1
if(dp[len][last][flag][zero] != -1) return dp[len][last][flag][zero];
int ans = 0;
for(int i = 0; i <= 9; i++) {
if((abs(i - last) >= 2 || zero) && ((flag && i <= num[len]) || !flag)) {//当前面全为0的时候这一位不用管相差多少
ans += dfs(len - 1, i, flag && (i == num[len]), zero && (i == 0));
}
}
return (dp[len][last][flag][zero] = ans);
}
int calc(int x) {
memset(num, 0, sizeof(num));
len = 1;
while(x) {
int now = x % 10;
x /= 10;
num[len] = now;
len++;
}
for(int i = 0; i < 32; i++) {
for(int j = 0; j < 32; j++) {
for(int k = 0; k < 2; k++) {
for(int w = 0; w < 2; w++) {
dp[i][j][k][w] = -1;
}
}
}
}
return dfs(len, 11, 1, 1);
}
int main() {
cin >> a >> b;
cout << calc(b) - calc(a - 1);
return 0;
}