背包问题的几种解法及变形
来源:互联网 发布:电商源码 编辑:程序博客网 时间:2024/06/09 22:44
背包问题
一、01背包
问题描述:
•给定n种物品和一个背包, 物品i的重量是wi, 价值是vi, 背包容量为W
•对于每个物品,要么装背包,要么不装
•选择装背包的物品集合,使得物品总重量不超过背包容量W, 且价值和尽量大
•对于每个物品,要么装背包,要么不装
•选择装背包的物品集合,使得物品总重量不超过背包容量W, 且价值和尽量大
限制条件: 1<=n<=100 1<=wi,vi<=100 1<=W<=10000
输入:
4 5
2 3
1 2
3 4
2 2
输出:
7
4 5
2 3
1 2
3 4
2 2
输出:
7
i表示物品编号
j表示剩余背包容量
j表示剩余背包容量
1.首先给出最朴素的方法,针对每个物品是否放入背包进行搜索
时间复杂度:O(2^n)
时间复杂度:O(2^n)
#include<iostream>#define M 100using namespace std;int n, W;int w[M], v[M];//从第i个物品开始挑选总重小于j的部分int ret(int i, int j){ int res; if(i == n)//已经没有剩余的物品 res = 0; else if(j < w[i])//当前物品无法放入 res = ret(i+1, j); else//当前物品放入和不放,取二者最大值 res = max(ret(i+1,j), ret(i+1, j-w[i])+v[i]); return res;}int main(){ cin>>n>>W; for(int i = 0; i < n; i++) { cin>>w[i]>>v[i]; } cout<<ret(0, W)<<endl; return 0;}
2.由于上面的方式时间复杂度较大,下面给出了利用记忆数组dp进行优化的方法,把第一次的计算结果记录下来,省掉了以后的计算
时间复杂度:O(nW)
#include<iostream>#include<string.h>#define M 100using namespace std;int n, W;int w[M], v[M];int dp[M+1][M+1];//从第i个物品开始挑选总重小于j的部分int ret(int i, int j){ if(dp[i][j] >= 0) return dp[i][j]; int res; if(i == n)//已经没有剩余的物品 res = 0; else if(j < w[i])//当前物品无法放入 res = ret(i+1, j); else//当前物品放入和不放,取二者最大值 res = max(ret(i+1,j), ret(i+1, j-w[i])+v[i]); return dp[i][j] = res;}int main(){ cin>>n>>W; for(int i = 0; i < n; i++) { cin>>w[i]>>v[i]; } memset(dp, -1, sizeof(dp)); cout<<ret(0, W)<<endl; return 0;}
3.穷竭搜索
#include<iostream>#include<string.h>#define M 100using namespace std;int n, W;int w[M], v[M];//sum为目前放入物品的价值总和int ret(int i, int j, int sum){ int res; if(i == n)//已经没有剩余的物品 res = sum; else if(j < w[i])//当前物品无法放入 res = ret(i+1, j, sum); else//当前物品放入和不放,取二者最大值 res = max(ret(i+1,j,sum), ret(i+1, j-w[i], sum+v[i])); return res;}int main(){ cin>>n>>W; for(int i = 0; i < n; i++) { cin>>w[i]>>v[i]; } cout<<ret(0, W, 0)<<endl; return 0;}
4.动态规划
dp[0][j] = 0
dp[i+1][j] = dp[i][j] (j<w[i])
dp[i+1][j] = dp[i][j] (j<w[i])
= max(dp[i][j],dp[i][j-w[i]]+v[i]) 其他
#include<iostream>#include<string.h>#define M 100using namespace std;int n, W;int w[M], v[M];int dp[M+1][M+1];int main(){ int i, j; cin>>n>>W; for(i = 0; i < n; i++) { cin>>w[i]>>v[i]; } memset(dp, 0, sizeof(dp)); for(i = 0; i < n; i++) { for(j = 0; j <= W; j++) { if(j<w[i]) dp[i+1][j] = dp[i][j]; else dp[i+1][j] = max(dp[i][j],dp[i][j-w[i]]+v[i]); } } cout<<dp[n][W]<<endl; return 0;}
二、完全背包
问题描述:
•给定n种物品和一个背包, 物品i的重量是wi, 价值是vi, 背包容量为W
•对于每个物品,要么装背包,要么不装
•选择装背包的物品集合,使得物品总重量不超过背包容量W, 且价值和尽量大
•给定n种物品和一个背包, 物品i的重量是wi, 价值是vi, 背包容量为W
•对于每个物品,要么装背包,要么不装
•选择装背包的物品集合,使得物品总重量不超过背包容量W, 且价值和尽量大
•每种物品可选多件
输入:
3 7
3 4
3 7
3 4
4 5
2 3
输出:
10
输出:
10
1.一个三层循环的dp,它的时间复杂度是O(nW^2),效率并不高
dp递推式
dp[0][j] = 0
dp[i+1][j] = max(dp[i+1][j], dp[i][j-k*w[i]+k*v[i]) (k*w[i] <= j)
dp[i+1][j] = max(dp[i+1][j], dp[i][j-k*w[i]+k*v[i]) (k*w[i] <= j)
#include<iostream>#include<string.h>#define M 100using namespace std;int n, W;int w[M], v[M];int dp[M+1][M+1];int main(){ int i, j, k; cin>>n>>W; for(i = 0; i < n; i++) { cin>>w[i]>>v[i]; } memset(dp, 0, sizeof(dp)); for(i = 0; i < n; i++) { for(j = 0; j <= W; j++) { for(k = 0; k *w[i] <= j; k++) dp[i+1][j] = max(dp[i+1][j],dp[i][j-k*w[i]]+k*v[i]); } } cout<<dp[n][W]<<endl; return 0;}
2.优化:修改递推式 时间复杂度为O(nW)
dp[i+1][j] = dp[i][j] (j < w[i])
= max(dp[i][j],dp[i+1][j-w[i]]+v[i]) 其他
#include<iostream>#include<string.h>#define M 100using namespace std;int n, W;int w[M], v[M];int dp[M+1][M+1];int main(){ int i, j, k; cin>>n>>W; for(i = 0; i < n; i++) { cin>>w[i]>>v[i]; } memset(dp, 0, sizeof(dp)); for(i = 0; i < n; i++) { for(j = 0; j <= W; j++) { if(j<w[i]) dp[i+1][j] = dp[i][j]; else dp[i+1][j] = max(dp[i][j],dp[i+1][j-w[i]]+v[i]); } } cout<<dp[n][W]<<endl; return 0;}
0 0
- 背包问题的几种解法及变形
- 背包问题的几种解法总结
- 0-1背包问题的几种不同解法
- 变形的背包问题
- 背包问题的变形
- 01背包问题的三种解法
- 01背包的几种解法(未完待续)
- 背包分组问题的解法
- 背包问题的解法源代码
- 背包问题的haskell解法
- 一种背包问题的解法
- 背包问题的递归解法
- 约瑟夫环问题的几种解法
- 约瑟夫问题的几种解法
- 约瑟夫问题的几种解法
- 【算法】逆序对问题的四种解法(归并排序,BST,树状数组,线段树)及变形
- 01背包类型问题的两种解法
- 背包方案及变形
- 字符驱动程序设计学习笔记4-2
- Python 3.3 (2)
- java中的volatile和transient关键字
- Windows下Qt 5.2 for Android开发入门
- 苹果iMessage垃圾信息泛滥:运营商难涉及
- 背包问题的几种解法及变形
- ORACLE分区表、分区索引(转)
- Tiny4412第一个qtopia2.2.0测试程序mycalc
- ORACLE SEQUENCE用法
- 打电话、发短信
- uva 539 - The Settlers of Catan(搜索)
- HttpClient4 Post XML数据
- 蓝桥杯 幂方分解
- IEC61850变电站基本通信结构-原理和模型_2信息信息交换模型