博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
01背包、完全背包、多重背包
阅读量:5126 次
发布时间:2019-06-13

本文共 5334 字,大约阅读时间需要 17 分钟。

参考(都有些错误):

 

#include 
#include
#include
#include
using namespace std;/*01背包问题 每个物品仅一个状态转移公式:F[i][j] = F[i - 1][j] 和 F[i - 1][j - W[i]] + V[i] 大的那个值C背包总重量W每个物品重量V每个物品价值n物品总数inp具有最大价值时,标记哪个物品在包中返回最大价值*/int packages(int C, vector
&W, vector
&V, int n, vector
&inp){ vector
> F(n, vector
(C + 1));//F[i][j]记录背包可用重量为j时,前i个物品的最大价值 for (int i = 0; i < n; i++)//初始化表格 { for (int j = 0; j < F[0].size(); j++) F[i][j] = 0; } for (int j = 1; j < F[0].size(); j++)//初始化第一行 F[0][j] = (j < W[0]) ? 0 : V[0];//可用重量j大于物品重量,则装入该物品,加上该物品价值 for (int i = 1; i < n; i++) { for (int j = 1; j < F[0].size(); j++) { if (j < W[i]) F[i][j] = F[i - 1][j];//装不下该物品 else F[i][j] = (F[i - 1][j] < F[i - 1][j - W[i]] + V[i]) ? F[i - 1][j - W[i]] + V[i] : F[i - 1][j];//可装下该物品。状态转移方程 } } int result = F[n - 1][F[0].size() - 1];//最大价值 //inp标记哪些物品在包中 int j = C; for (int i = n-1; i >0 ; i--)//i不可为0,否则F[i-1]越界 { if (j>W[i] && F[i][j] == F[i - 1][j - W[i]] + V[i])//注意需要j>W[i] { inp[i] = 1; j -= W[i]; } } if (F[0][j] > 0)//如果背包还可装下,则包含第一个物品 inp[0] = 1; //输出动态规划数组 for (int i = 0; i < n; i++) { for (int j = 0; j < F[0].size(); j++) cout << F[i][j] << " "; cout << endl; } return result;}/*01背包问题 滚动数组优化动态规划的空间原空间OnC,先空间O2C,但是无法输出有哪些物品在包中*/int packages_good(int C, vector
&W, vector
&V, int n){ vector
> F(2, vector
(C + 1));//F[i][j]记录背包可用重量为j时,前i个物品的最大价值 for (int i = 0; i < 2; i++)//初始化表格 { for (int j = 0; j < F[0].size(); j++) F[i][j] = 0; } for (int j = 1; j < F[0].size(); j++)//初始化第一行 F[0][j] = (j < W[0]) ? 0 : V[0];//可用重量j大于物品重量,则装入该物品,加上该物品价值 int k = 0; for (int i = 1; i < n; i++) { k = i & 1;//滚动 for (int j = 1; j < F[0].size(); j++) { if (j < W[i]) F[k][j] = F[k ^ 1][j];//装不下该物品 else F[k][j] = (F[k ^ 1][j] < F[k ^ 1][j - W[i]] + V[i]) ? F[k ^ 1][j - W[i]] + V[i] : F[k ^ 1][j];//可装下该物品 } } return F[k][F[0].size() - 1];//最大价值}/*完全背包 每个物品不限制数量状态转移公式:F[i][j] = F[i - 1][j] 和 F[i][j - W[i]] + V[i] 大的那个值,标记哪些物品在包中也改变注意是F[i][j - W[i]] + V[i]也可优化空间*/int packages_full(int C, vector
&W, vector
&V, int n, vector
&inp){ vector
> F(n, vector
(C + 1));//F[i][j]记录背包可用重量为j时,前i个物品的最大价值 for (int i = 0; i < n; i++)//初始化表格 { for (int j = 0; j < F[0].size(); j++) F[i][j] = 0; } for (int j = 1; j < F[0].size(); j++)//初始化第一行 F[0][j] = (j < W[0]) ? 0 : ((j/W[0])*V[0]);//每个物品不止一个 for (int i = 1; i < n; i++) { for (int j = 1; j < F[0].size(); j++) { if (j < W[i]) F[i][j] = F[i - 1][j];//装不下该物品 else F[i][j] = (F[i - 1][j] < F[i][j - W[i]] + V[i]) ? F[i][j - W[i]] + V[i] : F[i - 1][j];//可装下该物品。状态转移方程 } } int result = F[n - 1][F[0].size() - 1];//最大价值 //inp标记哪些物品在包中 int j = C; int i = n - 1; while (i) { while(j && j > W[i] && F[i][j] == F[i][j - W[i]] + V[i]) //如果包含该物品,则一直循环看包含几个该物品 { inp[i]++; j -= W[i]; } i--;//不包含该物品,则跳到下一个物品 } //输出动态规划数组 for (int i = 0; i < n; i++) { for (int j = 0; j < F[0].size(); j++) cout << F[i][j] << " "; cout << endl; } return result;}/*多重背包 每个物品有数量限制*/int packages_multi(int C, vector
&W, vector
&V, int n, vector
&inp, vector
&N)//N会被修改{ vector
> F(n, vector
(C + 1));//F[i][j]记录背包可用重量为j时,前i个物品的最大价值 for (int i = 0; i < n; i++)//初始化表格 { for (int j = 0; j < F[0].size(); j++) F[i][j] = 0; } for (int j = 1; j < F[0].size(); j++)//初始化第一行,每个物品有对应数量N限制 { int count = (N[0] > j / W[0]) ? j / W[0] : N[0];//可用空间为j时,可以放多少个当前物品,min{可放入数量,物品数量} F[0][j] = (j < W[0]) ? 0 : (count*V[0]); } for (int i = 1; i < n; i++) { for (int j = 1; j < F[0].size(); j++) { if (j < W[i]) F[i][j] = F[i - 1][j];//装不下该物品 else { int count = (N[i] > j / W[i]) ? j / W[i] : N[i]; F[i][j] = F[i - 1][j];//不放当前物品 for (int k = 1; k <= count; k++)//看放入多少个当前物品可以让F[i][j]最大 { int tmp = F[i - 1][j - k * W[i]] + k * V[i];//放入k个当前物品 if (tmp > F[i][j]) F[i][j] = tmp; } } } } int result = F[n - 1][F[0].size() - 1];//最大价值 cout << result << endl; //inp标记哪些物品在包中 int j = C; int i = n - 1; while (i) { while (j && N[i] && j > W[i] && F[i][j] == F[i][j - W[i]] + V[i]) //如果包含该物品,则一直循环看包含几个该物品 { inp[i]++; j -= W[i]; --N[i]; } i--;//不包含该物品,则跳到下一个物品 } //输出动态规划数组 for (int i = 0; i < n; i++) { for (int j = 0; j < F[0].size(); j++) cout << F[i][j] << " "; cout << endl; } return result;}int main() { vector
W{ 4,5,6,2,2 }; vector
V{ 6,4,5,3,6 }; int C = 9; int n = W.size(); vector
inp(n, 0);//标记是否在包中 cout << "1、01背包最大总价值:" << packages(C, W, V, n, inp) << endl; cout << "在背包中的物品编号: "; for (int i = 0; i < inp.size(); i++) { if (inp[i] == 1) cout << i << " "; } cout << endl; cout << "2、01背包滚动数组优化最大总价值,无法输出有哪些物品在背包中:" << packages_good(C, W, V, n) << endl; cout << endl; vector
inp1(n, 0);//标记是否在包中 cout << "3、完全背包最大总价值:" << packages_full(C, W, V, n, inp1) << endl; cout << "输出在背包中物品: "; for (int i = 0; i < inp1.size(); i++) { cout << inp1[i] << " "; } cout << endl; cout << endl; vector
N{ 1,2,2,2,4 };//每个物品数量 vector
inp2(n, 0);//标记是否在包中 cout << "4、多重背包最大总价值:" << packages_multi(C, W, V, n, inp2, N) << endl; cout << "输出在背包中物品: "; for (int i = 0; i < inp2.size(); i++) { cout << inp2[i] << " "; } cout << endl; return 0;}

 

转载于:https://www.cnblogs.com/beixiaobei/p/10914211.html

你可能感兴趣的文章
仓库服务端软件artifactory
查看>>
Vulkan(0)搭建环境-清空窗口
查看>>
Vulkan(1)用apispec生成Vulkan库
查看>>
python全栈开发中级班全程笔记(第三模块、第一章(1.面向对象基础))
查看>>
python全栈开发中级班全程笔记(第三模块、第一章(多态、封装、反射、内置方法、元类、作业))...
查看>>
python全栈开发中级班全程笔记(第三模块、第二章(网络编程))
查看>>
30分钟部署一个Kubernetes集群
查看>>
gitlab部署
查看>>
gitlab数据迁移
查看>>
samba安装配置
查看>>
redis数据备份还原
查看>>
centos7 dns(bind)安装配置
查看>>
Keepalived+LVS+nginx搭建nginx高可用集群
查看>>
CAA调试
查看>>
BZOJ3123[Sdoi2013]森林——主席树+LCA+启发式合并
查看>>
BZOJ3523[Poi2014]Bricks——贪心+堆
查看>>
Android 二维码 生成和识别(附Demo源码)
查看>>
查询sql server占用内存的情况
查看>>
react-01
查看>>
sublime插件安装
查看>>