hdu 2089 不要62(数位dp入门)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089
一道数位dp的入门题,数据超级小完全可以用暴力过,当然用记忆化搜索写更好,能练练数位dp
的记忆化搜索的写法。
开始要找dp的设法,首先必要的一维是长度,然后第二维可以存前一个数也可以表示状态,这里
要选择表示状态。如果选择存前一个数这样不好,因为返回的dp要要求不含有不吉利的数字,所
以这里优先考虑dp[len]这些数是否要满足要求,所以第二维要设state表示状态,只返回状态满
足要求的dp值。
#include <iostream>
#include <cstring>
using namespace std;
int n , m , dp[12][3] , dig[12];
int dfs(int len , int state , int flag) {
if(len == 0) {
return state < 2;
}
if(!flag && state < 2 && dp[len][state] != -1) {
return dp[len][state];
}
int t = flag ? dig[len] : 9;
int sum = 0;
for(int i = 0 ; i <= t ; i++) {
if(state == 0) {
if(i == 4) {
continue;
}
else {
if(i == 6) {
sum += dfs(len - 1 , 1 , flag && i == t);
}
else {
sum += dfs(len - 1 , 0 , flag && i == t);
}
}
}
if(state == 1) {
if(i == 2 || i == 4)
continue;
else {
if(i == 6) {
sum += dfs(len - 1 , 1 , flag && i == t);
}
else {
sum += dfs(len - 1 , 0 , flag && i == t);
}
}
}
}
if(!flag && state < 2) {
dp[len][state] = sum;
}
return sum;
}
int Gets(int x) {
memset(dp , -1 , sizeof(dp));
memset(dig , 0 , sizeof(dig));
int len = 0;
if(x == 0) {
dig[++len] = 0;
}
while(x) {
dig[++len] = x % 10;
x /= 10;
}
return dfs(len , 0 , 1);
}
int main() {
while(scanf("%d%d" , &n , &m) != EOF) {
if(n == 0 && m == 0) {
return 0;
}
printf("%d\n" , Gets(m) - Gets(n - 1));
}
return 0;
}

浙公网安备 33010602011771号