引用博客 https://blog.csdn.net/stpeace/article/details/46700657
0-1背包问题: 一个小偷来出来活动了, 拿了一个背包, 最多可以装50斤的东西的小袋子。 他眼睛一亮, 发现了三件宝贝a, b, c. 其中a重10斤, 价值60元; b重20斤, 价值100元; c重30斤, 价值120元。 问: 在背包允许的范围内, 小偷最多能偷到多少钱?
本想写个递推公式, 可是这CSDN写公式不太方便, 所以还是算了。 一旦有了递推公式, 要计算值, 那是计算机的长项, 直接给出代码吧, 代码蕴含一切(50斤=5十斤, 以十斤为一个单位, 方便编程):
#include<iostream>
using namespace std;
#define N 8 // N件宝贝
#define V 10 // C是背包的总capacity
int main()
{
int value[N + 1] = { 0, 120, 100, 60, 100, 160, 180, 20, 5 }; // 钱啊
int weight[N + 1] = { 0, 3, 2, 1, 5, 4, 3, 3, 2 }; // 重量
int f[N + 1][V + 1] = { 0 }; // f[i][j]表示在背包容量为j的情况下, 前i件宝贝的最大价值
int i = 1;
int j = 1;
for (i = 1; i <= N; i++)
{
for (j = 1; j <= V; j++)
{
// 递推关系式出炉
if ( j < weight[i] ) //j - weight[i]
{
f[i][j] = f[i - 1][j];
}
else
{
int x = f[i - 1][j];
int y = f[i - 1][j - weight[i]] + value[i];
f[i][j] = x < y ? y : x;
}
}
}
for (i = N; i >= 1; i--)
{
for (j = 1; j <= V; j++)
{
printf("%4d ", f[i][j]);
}
cout << endl;
}
getchar();
return 0;
}
j 代表啥?(便利数组所使用的数 for (j = 1; j <= V; j++) )
weight[i] 0, 1, 2, 3如上所示
↓ f[i][j]的意义
if (j < weight[i]), else的作用 判断当前所拥有容量与重量的差值
↓插值 < 0
f[i][j] = f[i - 1][j] 意义 此时包内容量为上轮容量及包内价值为上轮价值
↓插值 > 0
int x = f[i - 1][j]; 上轮容量及包内价值为上轮价值
int y = f[i - 1][j - weight[i]] + value[i]; 当 j = weight时,vaule[i], 当 j > weight时,上轮容量及包内价值为上轮价值 + value[i]
俩意义
↓
此时f[i][j]的值更新的意义 通过比较x与y获取当前最优!
递推公式的思想就是 数列, 从a1, a2, a3, , , , , an,,所以才有一下这种情况
上轮的意思是,
i = 1(只能拿一个物品且为weight数组和value数组的第一个元素的值),
i = 2(只能拿两个个物品且为weight数组和value数组的第一个元素的值和第二个元素的值)
当当前所拥有容量与重量的差值 < 0时 通过f[i][j] = f[i - 1][j]; 获取上轮最优
当当前所拥有容量与重量的差值 >= 0是 通过int x = f[i - 1][j]; int y = f[i - 1][j - weight[i]] + value[i]; 获取当前最优!