上周发了专题细研,就选了其中一个专题开始研究,这周学的是动态规划的数位dp和状压dp,说到动态规划,其实在上学期就学过,那个时候的动态规划主要还是直接写出状态转移方程就行了,这次虽然主要的方程还是状态转移,不过更加的深入了,增加了他的应用场景,所谓数位dp就是将其在数位上进行微量处理的动态规划手段,一开始的几天看了很多大佬的博客里关于数位dp的内容感觉说的云里雾里的尤其是前面那几个一开始就讲什么区间什么分解建树,导致我一直在研究他的建树,后来发现其实我的研究方向错了,我想到这里的专题是动态规划,而动态规划最主要的还是状态的转移,而且这第一个分支是数位dp也就是说研究的应该是数位上的状态转移,然后我看了这个大佬的博客这时我才感觉豁然开朗,我还发现这个数位dp的方法跟之前我学高精度的时候一样也是在研究数位上的关系,不过这里加了状态,
板子题:
Problem - 2089 不要62(hdu.edu.cn)
P2657 [SCOI2009] windy 数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
核心代码的板子:
int dfs(int pos,/*当前位数*/,bool lead/*前导零*/,bool limit/*数位上界*/)
{
if(pos==-1)///递归边界,既然是按位枚举,最低位是0,那么pos==-1说明这个数我枚举完了
return 1;
if(!limit && !lead && dp[pos]!=-1)///第二个就是记忆化(在此前可能不同题目还能有一些剪枝)
return dp[pos];
int End=limit?a[pos]:9;//根据limit判断枚举的上界End;
int ans=0;
//开始计数
for(int i=0; i<=End; i++) ///枚举,然后把不同情况的个数加到ans就可以了
{
if()///里面的选择判断要根据题中要求来判断
...
else if()
...
ans+=dfs(pos-1,/*状态转移*/,lead && i==0,limit && i==End)
///!!!最后重要的转移式
}
if(!limit && !lead)///这里对应上面的记忆化,在一定条件下时记录,保证一致性.
dp[pos]=ans;
return ans;
}
一开始研究这个数位dp也挺费脑子的看了后面的状压dp和概率dp感觉也是挺难的,看了很多题,这个板子还是用的很不熟练,下周就打算继续先看这个数位dp 的题目,再熟悉熟悉这个板子,然后继续下面的内容了。