hdu2089不要62
中文题就不写题意了,也不是很难理解。
主要用到的数位dp的方法,一种记忆化搜索的dp方法
刚刚开始学还不是很熟悉这个模板,所以代码不是自己写的,等等我会再去写几遍,给了很多注释来帮助理解,希望能对你有帮助。
# include <iostream>
# include <stdio.h>
# include <cstring>
# include <string>
using namespace std;
typedef long long LL;
int a[20];//存储每一位的限制。
int dp[20][2];
/*
dp[pos][sta]
pos:当前是第几位
sta前一位是否为6:
为6为0
不为6为1
*/
int dfs(int pos, int pre, int sta,bool limit) {
/*
pos:当前在第几位
pre:上一位的数字是什么
sta:上一位是否是6
limit:当前位是否要遵循a数组的限制。
*/
if(pos == -1) return 1;//当前位为-1位,即不存在的。。直接返回就好,相当于在第0位返回1
if(!limit && dp[pos][sta] != -1) return dp[pos][sta];//当前位不被限制,且dp中已存在值,则直接返回这个值
int up = limit ? a[pos] : 9;//判断是否有限制,没有就直接枚举到9
int tmp = 0;//把当前情况下的所有情况个数存下来
for(int i = 0; i <= up; i++) {
if(pre == 6 && i == 2) continue;
if(i == 4) continue;
tmp += dfs(pos-1,i,i == 6, limit && i == a[pos]);
}
if(!limit) dp[pos][sta] = tmp;//当前位不被限制,则记忆化当前值。
/*
为什么要区分当前位是否被限制来判断是否记忆化?
因为当前位是否被限制是不在二维dp的状态里的,这里的两种状态明显值是不同的,
记忆化过程中,不被限制时的值更能节省时间,被限制的情况在搜索中是少数,所以
其实不会太影响程序的运行速度,当然,可以给出三维dp的状态,只不过在本题目中
没有必要。
*/
return tmp;
}
int solve(int x) {//解决的问题是:从1到x有多少个车牌满足条件
int pos = 0;
while(x) {
a[pos++] = x%10;
x /= 10;
}
return dfs(pos-1,-1,0,true);
}
int main() {
int le,ri;
while(~scanf("%d%d",&le,&ri) && le+ri) {
memset(dp,-1,sizeof(dp));
printf("%d\n",solve(ri) - solve(le-1));
}
return 0;
}