1.数位dp,可以利用dfs来暴力搜索,dp来继续记忆化的减枝,适合用于解决高的数量级的,跟数的位数有关系的问题
2.dp[pos][sta],pos表示的是遍历的数的层数(例如十位百位千位),层数是从大到小的,遍历到-1层则表示当前的数已经形成,则可以返回当前的数的在问题中所计算出的值temp,sta表示的是对于题目,有些不同的数据可以有的相同的状态,例如:hdu中的不要62(统计一个区间中没有4和62出现的数的数目为多少),显然不同的位数相同的状态就是是否含有6,dp[pos][sta]//sta表示是否含有6,有为1无为0,当百位为0,十位为6时,要调用的是dp[0][1](dp[0][1]={0,1,3,4,5,6,7,8,9}=9),而不是dp[0][0]={0,1,2,3,4,5,6,7,8,9}=10
模板:
int a[pos]//用来储存实际参数的各个数位的值
int dp[pos][sta] //pos用来表示当前的层数,sta用来表示可以公用的状态
int dfs(int pos,int sta,bool limit)//pos表示下一层是哪一层,sta下一个层数遍历的位置可一公用的状态,limit用来限制当前的层数是否需要限制最高的遍历的数
{
int i,j;
if(pos==-1)
{
return 1;//当前的数成型返回结果
}
if(!limt&&dp[pos][sta]!=0)
{
return dp[pos][sta];//记忆化的好处体现在这里,如果遇到可以公用的状态则可以直接的调用,需要没有限制才可以调用,因为调用的dp[pos][sta]表示的是前一层数的结果例如(214),百位为2时,十位只能是0,1如果遍历dp[1][sta]则十位为0-9超出了范围
}
int up=limit?a[pos]:9;//确定范围
int temp=0;
for(i=0;i<=up;i++)
{
if().....//根据题意跳过不符合题意的结果
temp+=dfs(pos-1,sta...,limit&&i==up);
}
if(!limit)
dp[pos][sta]=temp;//记忆化
return temp;
}
int solve(int x)
{
int cnt=0;
while(x)
{
a[cnt++]=x%10;
x/=10;
}
return dfs(cnt,sta,1);
}