代码:
//0-1背包问题
#include <iostream>
#include <iomanip>
#include<algorithm>
using namespace std;
int main()
{
int n, m;//物品总件数,背包最大重量
int value[100][100];
int v[100];//当前物品的价值
int w[100];//当前物品的重量
cin >> n >> m;
for (int i = 1; i <= n; i ++) cin >> w[i] >> v[i]; //一个i对应一个物品
for (int j = 0; j <= m; j ++) value[0][j] = 0; //一个j对应一个重量,这里初始化的是向各个重量的背包中放0件物品,价值均为0
for (int i = 1; i <= n; i ++)//按放置物品的顺序填表(规定先放矿泉水,第二放书,...
{
value[i][0] = 0;//重量为0的背包价值为0
for (int j = 1; j <= m; j ++)
{
//面对当前商品有两种可能性:包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}
value[i][j] = value[i - 1][j];
if (j >= w[i])
value[i][j] = max(value[i - 1][j], value[i - 1][j - w[i]] + v[i]);
}
}
cout << "01背包各状态转换表:" << endl;
for (int i = 0; i <= n; i ++)
{
for (int j = 0; j <= m; j ++)
cout << setw(3) << value[i][j];
cout << endl;
}
cout << "背包能装的最大价值为:" << value[n][m];
return 0;
}
状态转移方程解释:value[x][y] = max{value[x - 1][y], value[x - 1][y - w[i]] + v[i]}
value[x][y]:当前状态的最大价值,也就是要填到小方格里的数
value[x - 1][y]:当前重量下不放此物品的价值
value[x - 1][y - w[i]] + v[i]:放此物品前上一个状态的价值 + 此物品价值 = 当前重量下放此物品后的价值
24.2.12更正:
放此物品前/后(×)
将此物品加入可放入背包的物品范围前/后(√)
更易懂的解释:
为什么要计算小背包可装入的商品最大价值?
后期大背包(即计算背包的更大重量)时,可以根据这些子问题的答案来确定:余下的空间应该装入哪些商品。
逐步计算最大价值(
运行结果:
补充:回溯根据最大价值推算背包中放置的物品是哪些(先鸽一会)