日记(周中)

61 篇文章 1 订阅
21 篇文章 0 订阅

    这几周要从数论和dp中选择一个学习,由于队友选择了数论,我就选择了dp,刚开始要学习数位dp。

    通过看了很多博客,知道了数位dp就是计数用的,最基础题型是计算一个区间(a,b)符合某个条件的数的个数。一般这种题就是枚举做,而数位dp就是一种暴力枚举的方法。它就是在数位上一位一位的枚举,使得这种枚举方式符合dp的定义,并且使用记忆化搜索,就会节省枚举的时间。

   一般这种题都有模板。

  

int a[20];
int dp[20][state];

int dfs(int pos,int zhuangtai,/*这里可能有很多状态*/int limit)
{
    if(pos==-1)return 1;//这里根据情况不一样,返回值不一样
    if(!linit&&dp[pos][state]!=-1/*如果有前导零的题,这里还有前导零的判断*/)return dp[pos][state];
    int sum=0;
    int end=limit?a[pos]:9;//这里是根据这一位数是否应该有限制,设置枚举的最大数,不过这是十进制的
    for(int i=0;i<=end;i++)//枚举循环
    {
        if()....//这里有许多限制条件。
        sum+=dfs(pos-1,/*状态或者前导零*/limit&&i==a[pos])
        
    }
    if(!limit/*有时候有前导零*/)dp[pos][state];
    return sum;


}

int solve(int x)
{
    int pos=0;
    while(x)
    {
        a[pos++]=x%10;
        x/10;
    }//这里是数位分解,一般十进制都是这样,
    return dfs(pos-1,/*状态限制*/,1);
}
int main()
{
    int q,w;
    while(~scanf("%d%d",&q,&w))
    {
        printf("%d\n",solve(q)-solve(w));
    }
    return 0;
}


      一般的限制条件有某个数中必须含有什么,或者能被什么整除什么的。整除的麻烦一点。
     这个是比较简单的一个模板,如果需要添加限制条件,有两种方法,一种是在dfs()函数里的枚举里添加条件,另外一个是直接在数组dp【pos】【state】后面再加一维或者很多维,当然数据量要小才可以。

     如果是条件很多就在状态限制里多加几条,如果是有权值的,比如  HDU 4734  ,这个就需要另外建一个函数另外算权值,其他的差不多,就是里面有一个博主说的 减法的艺术  是比较不错的。

    还有就是有的要求不是十进制,是二进制的问题,这就把转换数位的地方变成二进制,并且把枚举的循环改成二进制就好了。

    所以总结来看,数位dp的基本题型的简单题都可以套模板再加上变化一点就可以解决。

    至于难题,目前还没有看过这种题解或者见过这种题。------(其实感觉做不了)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值