数位Dp 学习笔记

前面

最近学了点数位DP,也码了几个题,写点学习笔记

数位DP

数位DP就是在数位上进行DP,(个位,十位,百位之类的)
一般数位DP,都会让求在某一区间内满足某一种限定的数的数量。
DP的方式一般是DFS+记忆化。
状态的话就是 dp[pos][..] d p [ p o s ] [ . . ] , pos p o s 表示第pos位状态为 .. . . 的满足题目限制的数量
对了…
一般我们在进行 dfs d f s 之前要对枚举上界进行分解,就是把各个位分离,这样既容易记录状态,也容易判断枚举的范围。
看一下代码应该就理解的差不多了.

int solve(int x)
{
    pos=0;//一定要记住啊每一次都要变成0,写题的时候老是忘
    while(x)
    {
        a[pos++]=x%10;//把各个位分离开
        x/=10;
    }
    return dfs(pos-1,....,true);
}

下面说一下 dfs d f s 的时候对于上界的控制:
我们在 solve s o l v e 里对枚举上界进行了拆分,
然后我们在 dfs d f s 的时候设置一个 bool b o o l 变量 limit l i m i t 来记录上一次 dfs d f s 是否到达的上一个位的上界,
如果到达了上一个位的上界,那我们在这一次 dfs d f s 的时候最大就只能枚举到这一位的上界
如果没有到达上一个位的上界,那么我们就可以一直枚举到 9 9 ;
举个例子:
假设我们枚举的上界是678,假如我们枚举第一位也就是百位是 6 6 的话,那我们第二位也就是十位就只能枚举到7是不是,如果大于 7 7 的话就会超过枚举上界;相反,假如我们在枚举第一位的时候百位小于6,那么我们第二位就可以在 09 0 − 9 之间任意枚举了。因为 5XX 5 X X 显然小于 678 678 .
对于上界的控制还需要注意的就是在开始 dfs d f s ,要把 limit l i m i t 设置成为 true t r u e ,这样才能保证枚举一直不超过上界。
然后是对于前导 0 0 的处理:
和上界控制差不多,对于前导0我们也是用一个 bool b o o l 变量 lead l e a d 来进行控制。
假若上一位是存在前导 0 0 且当前位又恰好选择了0,那么 lead l e a d true t r u e ;反之为 0 0

然后就是对于dfs的讲解了:

    //分别是枚举的位数,状态,是否到达枚举上界,是否有前导0
    int dfs(int pos,int S,int limit,int lead)
    {
        if(pos==-1) //因为上面是从pos=0开始拆分的所以这个是搜索的结束
            return 1;//对于返回:一般的题目中都是要对最后的状态进行判断,合法的话返回1,不合法的话返回0,做题多了也就了解套路了
        if(dp[pos][S]==-1 && !limit && !lead) //对于没有特殊情况的话,直接上记忆化搜索
            return dp[pos][S];
        int up=limit ? a[pos] : 9;//这里是上界判断
        int ans=0;//记录答案
        for(int i=0;i<=up;i++)//开始枚举当前位所选的数字
        {
            ........//一般会有一些判断
            ans+=dfs(pos-1,S...,limit && i==up,lead && i==0);
            //假若上一位到达了枚举上界且这一位也是枚举上界的话,那么下一位也必须是枚举上界,两个条件缺一不可。
            //lead是用来判断前导0
        }
        if(!limit && !lead) //除去特殊情况,进行记忆化
            dp[pos][S]=ans;
        return ans; //返回
    }

题目

学完数位 DP D P 之后也码了几道题,在我的博客里都有题解.(按照我做的顺序给出)
1.不要62 —————— 题解
2.HDU4734——————题解
3.POJ3252——————题解
4.HDU3709——————题解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值