动态规划
动态规划
背包模型
1 | Dp{ |
01背包问题
n个物品和一个容量为v的背包,每一个物品体积vi,价值wi,每件物品只能用一次.
求背包能装的下的情况下能装下的最大价值为多少,我们考虑有递推式:
1 | dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]) |
再空间优化:
1 | for(int i=1;i<=n;i++) |
完全背包问题
每件物品可以用无限次,只要装得下。
状态转移方程代码:
1 | dp[i][j]=max(dp[i-1][j],dp[i-1][j-k*v[i]]+k*w[i]) |
我们考虑对其做优化,参考01背包,先对空间做优化,然后我们可以推导出
对比上两个方程我们可以推导出:
实现代码:
1 | for(int i=1;i<=n;i++) |
多重背包问 题
每件物品的数量有限制,各为 Si:
1.朴素版
核心思想:二进制优化;
我们将s[i]拆分成二进制表示的1,2…2^k,其中2^k<=s[i]/2
然后转化成01背包来做
其中k=0,1,2…s[i]
我们将dp数组的行进行压缩可以得到:
实现代码:
1 | for(int i=1;i<=n;i++) |
2.二进制优化版
我们可以将每个物品的数量s做二进制优化,即将每一个s拆分成1,2,4….2^k,s+1-2^(k+1)。这样我们可以使用这些数表示任意1-s区间内的每一个数,并且时间复杂度也可以从原来的O(nms)优化到O(nmlogs)。然后我们呢对于拆分出来的物品用01背包的思路来做即可;
代码:
1 | for(int i=1;i<=n;i++){ //二进制优化 |
分组背包问题
物品有n组,每一组有若干个,每一组最多选一个,求最大价值
因此本质上还是01背包问题,我们将其转化为01背包,只不过多一层循环k依次迭代更新每一组的各件物品;
1 | for(int i=1;i<=n;i++) |
关于题目的文字表述: