背包问题模板
来源:互联网 发布:纳米袜子 知乎 编辑:程序博客网 时间:2024/06/05 02:43
01背包
特点:每种物品只有一件
子问题定义状态
bag[i][v] : 前i件物品放到一个容量为v的背包中可以获得最大价值
转移状态方程
bag[i][v] = max(bag[i-1][v],bag[i-1][v-weight[i]] + value[i])
模板:
#include<iostream>#include<string.h>using namespace std;int main(){ int n = 3;//n件物品 int v = 5;//背包的容量 int weight[n+1] = {0,3,2,2};//第n件物品的重量 int value[n+1] = {0,5,10,20};//第n件物品的价值 //结果最大价值为30 int bag[n+1][v+1]; memset(bag,0,sizeof(bag));//数组初始化,必须包含头文件<string.h> for(int i = 1; i <= n; i++){//枚举物品 for(int j = 0; j <= v; j++){//枚举背包容量 if(j >= weight[i]){ bag[i][j] = max(bag[i-1][j],bag[i-1][j-weight[i]]+value[i]); }else{ bag[i][j] = bag[i-1][j]; } } } cout<<bag[n][v]<<endl;return 0; }
效率分析
以上算法的时间复杂度为O(N*V)
,空间复杂度也为O(N*V)
.其中,N 表示物品个数,V 表示背包容量这里,时间复杂度不可以在优化了,但是空间复杂度可以继续优化到O(V).
空间复杂度优化
关键:由二维数组bag[n][v]改为用一维数组bag[v]来保存中间变量。
关键代码修改:
int bag[v+1];memset(bag,0,sizeof(bag));for (int i = 1;i <= n;i++){//枚举物品 for (int j = v;j >= weight[i];j--){//枚举背包容量,防越界,j下限为 weight[i] bag[j] = max(bag[j],bag[j-weight[i]]+value[i]); }}cout<<bag[v]<<endl;
完全背包
每种物品的数量为无限
转移状态方程修改为:
bag[j] = max(bag[j],bag[j-k*weight[i]]+k*value[i]);
k:枚举能拿几件
完全背包主要加了一层循环来枚举可以拿走的物品数量count count = v/weight[i];
原因:原因:假如有背包容量为6,有一物品重量为1,价值为2。此时根据背包的重量,最多只能拿6件而已。
模板:
#include<iostream>#include<string.h>using namespace std;int main(){ int n = 3;//n件物品 int v = 5;//背包的容量 int weight[n+1] = {0,3,2,2};//第n件物品的重量 int value[n+1] = {0,5,10,20};//第n件物品的价值 //结果最大价值为40 int bag[v+1]; int count; memset(bag,0,sizeof(bag));//数组初始化,必须包含头文件<string.h> for(int i = 1; i <= n; i++){//枚举物品 for(int j = v; j >= weight[i]; j--){//枚举背包容量 count = j/weight[i];//在不超过当前背包容量的情况下,当前物品最多可以拿几件 for(int k = 0; k <= count; k++){ bag[j] = max(bag[j],bag[j-k*weight[i]]+k*value[i]); } } } cout<<bag[v]<<endl;return 0; }
多重背包
特点:每种物品的数量有上限
转移状态方程与完全背包相同:
bag[j] = max(bag[j],bag[j-k*weight[i]]+k*value[i]);
主要就是枚举数量count的取值变为 count = min(num[i],v/weight[i]);
原因:假如有背包容量为6,有一物品重量为1,价值为2,数量为10。虽然该物品有10件,但你的背包容量最多只允许你拿6件而已。
模板:
#include<iostream>#include<string.h>using namespace std;int main(){ int n = 3;//n件物品 int v = 8;//背包的容量 int weight[n+1] = {0,1,2,2};//第n件物品的重量 int value[n+1] = {0,6,10,20};//第n件物品的价值 int num[n+1] = {0,10,5,2};//第n件物品的上限数量 //结果最大价值为64 int bag[v+1]; int count; memset(bag,0,sizeof(bag));//数组初始化,必须包含头文件<string.h> for(int i = 1; i <= n; i++){//枚举物品 for(int j = v; j >= weight[i]; j--){//枚举背包容量 count = min(num[i],j/weight[i]);//在不超过当前背包容量的情况下,当前物品最多可以拿几件 for(int k = 0; k <= count; k++){ bag[j] = max(bag[j],bag[j-k*weight[i]]+k*value[i]); } } }return 0; }
关于背包问题的参考资料:
背包问题九讲笔记_01背包
背包问题九讲笔记_完全背包
背包问题九讲笔记_多重背包
阅读全文
0 0
- 部分背包问题模板
- 背包问题模板
- 背包问题_模板
- 简单背包问题模板
- 背包问题标准模板
- 背包问题模板
- 背包问题模板
- 背包问题模板
- 背包问题模板
- 01背包问题模板
- 多重背包问题模板
- 背包问题模板(01背包,完全背包,多重背包)
- 背包问题--0/1背包 【模板】
- 多重背包模板题 背包问题V2
- ACM_模板_背包问题
- 二维背包问题 + 代码模板
- 背包问题总结(模板)
- 多重背包问题(含模板)
- Java之面向对象
- 请求网络,绘制ListView
- 1801:斜率计算
- linux内核学习笔记1
- WOJ1115-An Excel-lent Problem
- 背包问题模板
- 反转单向链表
- vb.net 教程 20-2 base64图片转换 1
- hdu 1238 substring
- gitlab 权限设置
- 第一章 走近Java
- LeetCode#239. Sliding Window Maximum
- Burp Intruder-暴力猜解
- 1的个数 汉明距离