2017.10.22_数位dp模板分析

本文深入解析数位DP的基本概念及其应用技巧,通过讲解pos、pre、status等关键参数的作用,结合递归搜索实现状态转移,帮助读者理解数位DP解决特定计数问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数位dp模板分析:

pos:当前处理的位置——一般由高位到低位

pre:上一位的数字

status:要达到的状态,如果为1则可以认为找到了答案,到时候用于返回,给计数器加一

limit:是否受限,例:567,当前处理6这位(十位),如果前边取的是4,则可以在十位取0—9,前边取的数等于5,则十位数字就要限制在0—6,此时的limit为1作为标志

dp[pos][pre][status]数组保存这三个状态是因为往后转移的时候会遇到很多重复的情况


dfs(int pos,int pre,int status,int limit)

{

     if(pos<1)//已经搜到了尽头,返回1

     return 1;



     if(!limit&&dp[pos][pre][limit]!=-1)//dp里保存的是完整的,即不受限的答案,如果满足的话,就直接返回

     return dp[pos][pre][limit];

     int end=limit==1?dig[pos]:9;

     int ret=0;



    for(int i=0;i<=end;i++)

   {   

            ret+=dfs(pos-1,i,status||(pre==4&&i==9),(limit==1)&&(i==end));

      //往下搜的状态很巧妙,status用||表示如果前面找到了答案那么后边有没有就无所谓了,而limit用&&是因为只有前面受限,当前首先才能推出下一步也受限,,比如789,如果十位取了8,而百位小于7,则个位可随便取,而当十位取了8,百位取了7,个位就有限制了。上边用没有49做例子。

   }

if(!limit)

dp[pos][pre][satus]=ret;

return ret;

}

还有很多例题没有看,感觉数位dp'还是很好理解的。









     

     


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值