DP之数位,概率,树形总结

DP小练终于搞定了,前前后后用了两星期,这次练习,主要是练习数位,概率和树形dp,其中不乏有些很好的思想。
首先,我们来看看数位dp。一般的,数位dp都用于统计区间,满足一些性质的数的个数,格式都比较固定,究其本质,不外乎先查找【0, r】区间满足该性质的数的个数,然后再求出【0, l - 1】区间满足该性质的数的个数,然后相减即可。
这里给出一段我的模板
int digit[70];
ll dp[65][22][22];

ll dfs(int pos, int cnt4, int cnt7, int flag) {
    if(cnt4 > x || cnt7 > y) return 0;
    if(pos < 1) return (cnt4 == x && cnt7 == y);
    ll &ret = dp[pos][cnt4][cnt7];
    if(!flag && ret != -1) return ret;
    int up = flag ? digit[pos] : 9;
    ll ans = 0;
    for(int i = 0; i <= up; i++) {
        ans += dfs(pos-1, cnt4 + (i == 4), cnt7 + (i == 7), flag && i == up);
    }
    if(!flag) ret = ans;
    return ans;
}
ll cal(ll n) {
    int len = 0;

    while(n) {
        digit[++len] = n % 10;
        n /= 10;
    }
    return dfs(len, 0, 0, 1);
}

有时候,数位dp会存在一些变形,例如HDU3943要求找到具体的满足条件的区间内的最大值,这个我们利用二分搜索,枚举答案,在上一次dp的基础上,继续做dp,不断缩小解空间,找到最优解。
再例如HDU3709,我们需要枚举平衡位置,来进行dp然后查找最优解否则无法统计。

概率dp获益良多。
POJ3744,如果横着扫一遍 统计过去,那么时间开销太大了,由数据,我们发现埋雷的位置很少,我们从这下功夫,然后在画画,可以发现,决策为f[n] = a * f[n-1] + b * f[n-2],其中a, b是常数。于是,枚举雷前面的位置,然后用矩阵快速幂加速显然。
概率dp一般是顺着来的(因为起点为1的话,他的概率就为1,往后顺推容易计算)
期望dp一般是倒着来的(通常,把达到的目标状态期望设定为0)
概率dp和期望dp并不是很难,但是当我们根据题设条件列出方程的时候,化简是比较烦的,这时候需要的是细心和耐心。
再者,概率和期望想要学好,论文是必须要看的。
ZOJ3329是比较基础的,容易推到方程。
当我们遇到类似于POJ2151这种题,我们需要顺着+倒着想一次,然后才能利用条件概率的知识解出正确答 有时候,推导出来的方程,往往依赖于之前未计算出来的状态(多见于期望dp),我们可能需要迭代,或者分拆方程的方法,例如HDU4035,后面的值依赖于前面的节点,我们需要改变下原状态方程,用数学代换,再迭代,解出辅助方程的转移方法。

最后再谈谈树形dp,
树形dp有两种思维方式,一种是点分治,也就是说,当我们计算一个点时候,我们只需要计算以这个点为根的子树(这是理想情况下,蓝儿多数时候,是需要考虑到父亲甚至祖先节点的,这时候,我们长可以用陈启峰一张一弛解题之道的思想,科学的缩小或者放大解空间,直戳题目要害,问题才能迎刃而解)。还有一种是边分治,例如找树的重心。
此博客会根据以后对dp的理解持续更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值