【算法设计】背包问题2
来源:互联网 发布:苹果怎么设置网络优先 编辑:程序博客网 时间:2024/09/21 08:57
研究生课程系列文章参见索引《在信科的那些课》
之前整理了屈奶奶讲的背包问题,感谢cyh24童鞋留言,传我一份武林秘籍《背包问题九讲》,实践了一下文档里对空间复杂度的改进。
0-1背包问题
通过之前的分析,Fk(y) 表示只允许装前k 种物品,背包总重不超过y 时背包的最大价值。得到0-1背包的递推公式和边界条件:
对空间的优化主要在Fk(y),原本我们用两个循环实现:
for(int k=1;k<=N;k++){for(int y=1;y<=B;y++){if(y-w[k-1]<0){F[k][y]=F[k-1][y];tagi[k][y]=tagi[k-1][y]; }else{//允许装入k件物品,价值的两种情况://不装第k件物品或至少装1件第k件物品F[k][y]=F[k-1][y]>F[k][y-w[k-1]]+v[k-1] ? F[k-1][y]:(F[k][y-w[k-1]]+v[k-1]);tagi[k][y]=F[k-1][y]>F[k][y-w[k-1]]+v[k-1]?tagi[k-1][y]:k;}}}
实际并一定不需要F[N][B]的空间,如果内层循环以B...0递推,即下面的形式:
for(int k=1;k<=N;k++){for(int y=B;y>0;y--){F[y]=max{F[y],F[y-w[i]]+v[i]};}}
因为是以B...0倒序递推,则F[y]此时就是F[k-1][y]的值,而F[y-w]还未改变,仍为F[k-1][y-w]的值。因此可以用一维数组存储原来的优化函数信息。代码如下:
void ZeroOnePack(int F[],int tagi[],int v, int w,int k){for(int i=B;i>0;i--){if(i-w>=0&&F[i]<=(F[i-w]+v)){F[i]=F[i-w]+v;tagi[i]=k;}}}
完全背包问题
再看完全背包问题,即每个物品有无限件,不限每个物品装入的个数。得到递推关系和边界条件:
递归公式最主要的区别是Fk(y-wk)+vk,而非原来的Fk-1(y-wk)+vk,即物品可以在前k件中继续挑选。用一维数组时希望此时F[y]的数值即为F[k-1][y]的数值,而F[y-w]的数值为改变之后的F[k-1][y-w]的数值。因此我们可以用顺序0...B(而非逆序B...0)实现:
for(int k=1;k<=N;k++){for(int y=0;y>B;y++){F[y]=max{F[y],F[y-w[i]]+v[i]};}}
具体代码如下:
void CompletePack(int F[],int tagi[],int v, int w,int k){//F[i]=F[i]>(F[i-w]+v)?F[i]:(F[i-w]+v);//tagi=F[i]>(F[i-w]+v)?tagi:tagi+1;for(int i=1;i<=B;i++){if(i-w>=0&&F[i]<=(F[i-w]+v)){F[i]=F[i-w]+v;tagi[i]=k;}}}
测试用例
前面是0-1背包和完全背包的内层循环,还需要一个外层循环调用:
void Knapsack(int F[],int tagi[][B+1],int v[], int w[]){for(int i=0;i<B+1;i++){F[i]=tagi[0][i]=0;}for(int i=0;i<N+1;i++)tagi[i][0]=0;for(int i=0;i<N;i++){for(int j=0;j<B+1;j++)tagi[i+1][j]=tagi[i][j];//0-1背包ZeroOnePack(F,tagi[i+1],v[i],w[i],i+1);//完全背包//CompletePack(F,tagi[i+1],v[i],w[i],i+1);}}
还有之前文章的例子来测试,输出结果:
代码及文档下载:http://download.csdn.net/detail/xiaowei_cqu/4787977
参考资料:dd_engi等 《背包问题九讲》
(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu 未经允许请勿用于商业用途)
- 【算法设计】背包问题2
- 【算法设计】背包问题
- 【算法设计与分析基础】背包问题
- 背包问题 原理 算法2
- 贪心算法-背包问题2
- 算法分析与设计2017-2-背包问题的贪心算法
- 算法设计的背包问题-------------用贪心算法求解
- 算法分析与设计-15-背包问题的贪心算法
- 0-1背包问题的多种算法设计与分析
- 蛮力法:设计算法求解背包问题,并编程实现。
- 设计算法,在O(n)时间内求解分数背包问题
- 算法分析与设计-09- 0-1背包问题
- 算法设计与分析——0/1背包问题
- 背包问题的算法
- 递归算法 背包问题
- “背包问题”的算法
- 背包问题的算法
- 背包问题的算法
- android:使用SQLite的Blob储存.mp3档案
- [libexpat]_[XML处理]_[C/C++使用libexpat库以数据流(SAX模型)的方式读取(解析)大XML文件]
- #vi编辑器01# 删除与保存
- ArcGIS API for Silverlight 实现轨迹回放
- 三角星号
- 【算法设计】背包问题2
- android 推送消息 php做推送服务端(参考与http://fanfq.iteye.com/blog/1405385)
- 关于nio的java.nio.channels.CancelledKeyException的解决方法
- sqlplus命令行登录方法 as sysdba
- 数据结构基础(C++版)(张力译版)校正 之二 .
- 我的苹果开发帐号(公司型)成功申请经历——不用传真营业执照、免费获取邓白氏编码
- ununtu 12.04 LTS 使用过程的一些问题小结
- 对自己有用的一些文章收藏
- Uart2Socket:将PC的串口信息通过WiFi网络传输至安卓Android手机上