标签:背包 weight max 复杂度 value 01 动态 规划
昨天逛知乎,看见一个对完全背包时空复杂度优化的定量解法,觉得的非常好
于是,本篇博客,我将记录对01、完全背包中时间、空间复杂度优化的详解,作为昨天博客内容 动态规划——背包问题(一)01背包和完全背包 的补充
首先是题目
从上一篇文章中我们先列出了最开始的完全背包状态转移方程:
f[i][j]=max(f[i-1][j],f[i-1][j-k*weight[i]]+k*value[i]),(k*weight[i]<=j)
而01背包则是:
f[i][j]=max(f[i-1][j],f[i-1][j-weight[i]]+value[i])
那么,完全背包就是01背包的扩展,区别就是:
对于01背包问题,k=0,1;
对于完全背包问题,k=0,1,2,3,...,j/weight[i]
只要对k的范围稍作改动,二者完全可以统一
完全背包问题的算法优化:
1.时间复杂度优化
首先,我们将状态转移方程展开得到如下k+1个式子:
利用待定系数法,用j-weight[i]替换上式中的j得到:
等式两边同时加上value[i]:
此时,我们发现,三式中的(1)...(k)和一式中的(2)...(k+1)式重合
所以,原状态转移方程可以简化为:
f[i][j]=max(f[i-1][j],f[i][j-weight[i]]+value[i])
这样就把原来均摊时间复杂度为O(m)的状态转移优化到了O(1)
对于第i件物品,面临两种选择;一个也不拿:f[i-1][j]
和至少拿一个:f[i][j-weight[i]]+value[i]
,其实f[i][j-weight[i]]+value[i]
在一次又一次的遍历和比较之中已经通过不断的j-weight[i]
实现了k*weight[i]
;又通过不断的+value[i]
实现了+k*value[i]
,再通过一轮轮的max()
比较和覆盖,得出最后的值
2.空间复杂度优化
f[j]=max(f[j],f[j-weight[i]]+value[i])
可以看这张图:
深黄色格子就是代表了f[i][j]
,由于它取决于上面一行的f[i][j]
和同一行的f[i][j-weight[i]]
,因此在优化后的转移方程中,我们发现max()
的左值f[j]
即为原来处于上一行的f[i-1][j]
,右值中的f[j-weight[i]]+value[i]
即为原来处于同一行的f[i][j-weight[i]]+value[i]
,因为每次得到的结果都是二者的最大值,因此覆盖后得到的新的f[j]
完全可以保存当前的结果,参与下一轮循环
最后给出完全背包问题的代码:
#include<iostream>
using namespace std;
int N,M,weight[32]={0},value[32]={0},f[202]={0}; //N-物品种类数 M-背包的总容量
int main()
{
cin>>M>>N;
for(int i=1;i<=N;i++) cin>>weight[i]>>value[i];
for(int i=1;i<=N;i++){
for(int j=0;j<=M;j++){
if(weight[i]>j)
continue;
f[j]=max(f[j],f[j-weight[i]]+value[i]);
}
}
cout<<"max="<<f[M];
return 0;
}
本文完
标签:背包,weight,max,复杂度,value,01,动态,规划 来源: https://www.cnblogs.com/Sky6634/p/16493737.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。