0 - 1背包问题
问题描述:
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为W(假定物品重量与背包容量值均为整数),应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?设计一个动态规划算法,求解背包问题。
❗算法描述❗:
定义 w[] 存储各物品的重量,v[] 存储各物品的价值,背包的重量为 wsum。
①定义子问题:
k(w, j) = 容量剩余 w 时,从物品 1 到 j 能得到的最高价值。
②是否满足最优子结构:
k(w, j) = max( k(w - wj, j-1) + vj,k(w, j-1));
前者指,第 j 个物品放入背包中,则产生的最高价值就是,在背包容量为 w-wj的情况下,在 0 ~ j-1 这些物品中能产生的最高价值 + 第 j 个物品 的价值;
后者指,第 j 个物品不放入背包中,则产生的最高价值就是,背包容量还剩 w,在0 ~ j-1 这些物品中能产生的最高价值。
所以,
| 0, if w == 0 or j = 0
k(w, j) = | k(w, j-1), if w < wj
| max( k( w - wj, j - 1) + vj, k(w, j-1)), otherwise③确定解决子问题的次序:
自底向上,bottom - up。
④回溯最优解:
代码如下:
#include <iostream>
#include <vector>
using namespace std;
int max(int, int);
void knapsack(vector<vector<int>> k, vector<int> w, vector<int> v, int c, int num);
int main()
{
int num;
cout << "请输入物品个数:" << endl;
cin >> num;
vector<int> w(num + 1, 0);
vector<int> v(num + 1, 0);
cout << "请输入各物品的重量:" << endl;
for (int i = 1; i < num + 1; ++i)
{
cin >> w[i];
}
cout << "请输入各物品的价值:" << endl;
for (int i = 1; i < num + 1; ++i)
{
cin >> v[i];
}
int c;
cout << "请输入背包的容量:" << endl;
cin >> c;
vector<vector<int>> k(c + 1, vector<int>(num + 1));
for (int i = 0; i < c; ++i)
{
k[i][0] = 0;
}
for (int j = 0; j < num; ++j)
{
k[0][j] = 0;
}
for (int j = 1; j < num + 1; ++j)
{
for (int i = 0; i < c + 1; ++i)
{
//如果背包的剩余容量小于第 j 个物品的重量
if (i < w[j])
{
k[i][j] = k[i][j - 1];
}
//否则
else
{
k[i][j] = max(k[i - w[j]][j - 1] + v[j], k[i][j - 1]);
}
}
}
cout << "背包可能容纳物品的最大价值:" << endl;
cout << k[c][num] << endl;
knapsack(k, w, v, c, num);
cout << endl;
return 0;
}
//回溯结果
void knapsack(vector<vector<int>> k, vector<int> w, vector<int> v, int c, int num)
{
if (c >= w[1] && num > 0)
{
if (k[c][num] == k[c - w[num]][num - 1] + v[num])
{
cout << num << ' ';
knapsack(k, w, v, c - w[num], num - 1);
}
else if (k[c][num] == k[c][num - 1])
{
knapsack(k, w, v, c, num - 1);
}
}
else
{
return;
}
}
int max(int a, int b)
{
return a > b ? a : b;
}
一篇有趣的讲解:https://www.jianshu.com/p/a66d5ce49df5
一篇全面的讲解:https://wenku.baidu.com/view/fa370577ae1ffc4ffe4733687e21af45b307fe7a.html
版权声明:本文为t11383原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。