关于DP(抽象为背包问题的DP)

1.哪些可以抽象为背包类的DP

一般是涉及到有限制的选择问题,可以用背包问题来做

2.DP的复杂度计算:一般=状态数量 x 转移的计算量

3.关于DP的优化,分为时间和空间两个方面上(有时候只能优化空间,有时候时间和空间都可以优化)

优化时间:

一般是优化第三重循环:循环决策(子集),然后有一些巧妙的方法可以去掉第三重循环:循环决策(这个关于第几重循环后面会补充,先完整地看下去)

比如:

​
推导出的状态计算公式:

f[i][j] = f[i-1][j] + f[i-1][j-v] + f[i-1][j-2v] + f[i-1][j-3v]+.....


试着写出f[i][j-v]  ,就是等量代换,把第二维的j换成j-v

f[i][j-v] = f[i-1][j-v] + f[i-1][j-2v] + f[i-1][j-3v]+....



此时我们发现f[i][j-v] 与 f[i][j] 除了第一个,其余后面的一样,这样我们可以优化f[i][j]的计算

此时:
f[i][j] = f[i-1][j] + f[i][j-v]



优化后,把O(M)的计算量变成了O(1) , 也就是去掉了第三重循环:循环决策
这样就优化了时间

​

优化空间:

一般是通过代码变形来优化(代码本身的逻辑),而不是通过题目本身来优化

先写出朴素写法,然后判断是否可以去掉第一维(代码逻辑要一致),只保留第二维来做到优化空间

这个时候有个需要注意的点是:去掉第一维后,要判断第二重循环应从小到大还是从大到小

通俗地讲:朴素写法状态计算时 

若要用到上一层的状态,第二层循环就从大到小枚举

若用的是本层,第二层循环就从小到大枚举

比如01背包问题的模板:

先写出朴素做法,再通过代码等价变换来优化空间

for(int i=1;i<=n;i++)
        for(int j=0;j<=m;j++)
        {
            f[i][j]=f[i-1][j];
            if(j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
        }
........................................................................................

计算时第i层f[i][j]时,发现要用到i-1层的f[i-1][....]

所以应该从大到小枚举第二重循环

优化后为:

for(int i=1;i<=n;i++)
        for(int j=m;j>=v[i];j--)
            f[j]=max(f[j],f[j-v[i]]+w[i]);

最后补充一下上面遗留的第几重循环:

背包问题优化空间之后,循环顺序是一定不能变的

第一重循环:一定是循环物品

第二重循环:一定是循环体积

第三重循环:一定是循环决策(子集)

当然了这里提到的物品、体积都是背包问题模板中的说法,做题目时,要抽象出来"物品"、"体积”

最后欢迎大家补充或者指正!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值