简单的数位dp是怎样运行的

来源:互联网 发布:统计分析软件r 编辑:程序博客网 时间:2024/04/30 01:15
例一:HDU 2089 不要62
入门题。就是数位上不能有4也不能有连续的62,没有4的话在枚举的时候判断一下,不枚举4就可以保证状态合法了,所以这个约束没有记忆化的必要,而对于62的话,涉及到两位,当前一位是6或者不是6这两种不同情况我计数是不相同的,所以要用状态来记录不同的方案数。
dp[pos][sta]表示当前第pos位,前一位是否是6的状态,这里sta只需要去0和1两种状态就可以了,不是6的情况可视为同种,不会影响计数。
刚开始以为很难  ,呵呵 ,看懂后好简单啊;
我在代码上增加了输出的中间量
DFS递归会的话   继续往下看   (不会的先学深搜,不然你们会看晕的!!!)
以下黑体字是对你输入的样例后输出的结果的解释:先去复制代码输入样例试一下吧
pos=number   {{{{   表示第number层的开始     ;    pos=number     end  }}}}表示第number层的结束
up=number     表示for(i从0到up)
dp[pos][0]表示     第pos层没有限制的个数
dp[pos][1]表示        第pos层有限制的个数
例如dp【0】【0】=9;     代表   十位数是5(不是6就是没有限制)  个位数是0,1,2,3,5,6,7,8,9共九个
dp【0】【1】=8;代表  十位数是6   个位数是0,1,3,5,6,7,8,9共八个;
dp[1][0]=80;dp【1】【1】=71;后者比前者少了621,622,623,625,626.,626,627,628,629;
 百位数是6,说明十位数受限制了(不能是二)
空格空格空格空格空格空格空格   tmp表示当前{{{{  }}}}里的tmp值(总个数)
以下是我刚开始不理解代码的地方     解释一下(0.0)
int up=limit ? a[pos] : 9;表示当limit=1时up=a【pos】  表示当 limit=0 时up=9;
limit表示是否受限制        sta=1表示受限制的dp【】【1】  sta=0表示不受限制的dp【】【0】;
pre表示    当前位数的前一位是多少;
自己输入样例   看看数位dp是怎运行的吧  (dfs好好理解一下)
#include<iostream>#include<cstdio>#include<cstring>#include<string>using namespace std;typedef long long ll;int a[20];int dp[20][2];int dfs(int pos,int pre,int sta,bool limit){    if(pos==-1) return 1;    if(!limit && dp[pos][sta]!=-1) return dp[pos][sta];    int up=limit ? a[pos] : 9;    int tmp=0;    printf("\n\npos=%d  {{{{\n  up=%d  \n",pos,up);    for(int i=0;i<=up;i++)    {        printf("\ni=%d  ",i);        if(pre==6 && i==2)continue;        if(i==4) continue;//都是保证枚举合法性        tmp+=dfs(pos-1,i,i==6,limit && i==a[pos]);        printf("                                tmp=%d \n",tmp);    }    printf("\n\n pos=%d :end }}}}}}\n\n",pos);    if(!limit)    {        dp[pos][sta]=tmp;    printf("\n  dp[%d][%d]=%d\n",pos,sta,dp[pos][sta]);    }    return tmp;}int solve(int x){    int pos=0;    while(x)    {        a[pos++]=x%10;        printf("a[%d]=%d  ",pos-1,a[pos-1]);        x/=10;    }    printf("\n");    return dfs(pos-1,-1,0,true);}int main(){    int le,ri;//    memset(dp,-1,sizeof dp);可优化    while(~scanf("%d%d",&le,&ri) && le+ri)    {        memset(dp,-1,sizeof dp);        printf("%d\n",solve(ri)-solve(le-1));    }}
看懂的   你就能去看更复杂的数位dp了;
我只能帮你们理解一下    0.0


1 0
原创粉丝点击