数位DP的第一次试水(HDU 2089)

来源:互联网 发布:数据有效性设置 编辑:程序博客网 时间:2024/06/14 02:55

其实数位dp就是记忆化搜索的一种优化而已

优化都是一个思路,不做重复的事

数位dp就是这样的

不用数位dp时,400+ms AC,用数位dp 0ms AC这就是区别


其实最关键的就是这个limit

他表示如果在这一位随便取什么值都不会改变dp的值呢


思路都在注释里了,之间上代码吧

#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;//递归到最后一位都满足条件那就返回1    if(!limit && dp[pos][sta]!=-1) return dp[pos][sta];//dp[pos][sta]的之是被改变了的而且limit 这个limit是什么我们先不知道哈    //因为这是深搜嘛,所以我先会搜索到【pos】【sta】这个位置    //那么如果这个位置与约束条件完全没有关系的话(limit)    //我再搜到这个位置的时候直接返回dp【pos】【sta】就好啦    //当然咯,我要能返回的话就要要求dp【pos】【sta】已经被算出来了哇    //但是,介个dp到底有什么用呢,删了看看    //嗯那个,注释掉之后,过是过了但是时间复杂度,爆爆爆 爆炸啦    //我在仔细看看再    int up=limit ? a[pos] : 9;//如果limit就为a[pos]否则就为9  limit就是表示这里是第一位还是这是递归到后几位的东西我曹,就是一个看能不能取到9的东西                              //我只想说,哎呀woc    int tmp=0;    for(int i=0;i<=up;i++)//up表示在这个pos的上界哦    {        if(pre==6 && i==2)continue;//pre是上一个传下来的呐,然而还是不知道limit是干嘛的 QAQ        if(i==4) continue;//都是保证枚举合法性        tmp+=dfs(pos-1,i,i==6,limit && i==a[pos]);//如果在这递归到了i且i合法就递归下一位,这是从高位往低位递归的哦    }    if(!limit) dp[pos][sta]=tmp;//只有这里会改变dp的值呢    return tmp;//也就是说无论如何都要return tmp的}int solve(int x){    int pos=0;    while(x)    {        a[pos++]=x%10;        x/=10;    }    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));    }    return 0;}


原创粉丝点击