题目描述
01背包问题
有n个重量和价值分别为\(w_i,v_i\)的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值中总和的最大值。
限制条件
- 1 <= n <= 100
- 1 <= \(w_i,v_i\) <= 100
- 1 <= W <= 10000
样例输入
n = 4
(w,v) = {(2,3) (1,2) (3,4) (2,2)}
W = 5
样例输出
7(选择0,1,3号物品)
暴力求解
# include <iostream>
# include <algorithm>
using namespace std;
int n, W;
const int MAX_N = 10000;
int w[MAX_N], v[MAX_N];
int rec(int i, int j)
{
int res;
if (i == n)
{
res = 0;//在递归中,这也就相当于是循环的终止条件了
}
else if (j < w[i])//无法挑选物品
{
res = rec(i + 1, j);//采用递归的方法,对下一个物品进行挑选
}
else//挑选和不挑选都尝试一下
{
res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
//对于挑选的情况,因为采用了递归的方式,j 最为各个物品之间的和,每次当然要减去
//挑选出来的满足条件的上一个物品的重量,并且对于挑选出的满足条件的物品的价值进行相加
}
return res;
}
void solve()
{
printf("%d\n", rec(0, W));//从第0件物品开始挑选
}
int main()
{
cin >> n;
cout << "输入每个物品的重量";
for (int i = 0; i < n; i++)
{
cin >> w[i];
}
cout << "输入每个物品的价值";
for (int i = 0; i < n; i++)
{
cin >> v[i];
}
cout << "输入不能超过的最大的重量";
cin >> W;
solve();
return 0;
}
小结
- 对于这一段代码,rec(i + 1, j - w[i]) + v[i] 尤其是对于这个可以挑选的这一段代码
的解释,想了一一下,一开始是有一个j 作为标准,从第i个物品开始挑选重量 小于j的物品,如果挑选出
来一个这样的物品了,那么再挑选下一个物品的时候就必须要把前一个物品的重量减去,然后以这个新的
“重量”来挑选下一个物品,为什么要这样做呢,原因很简单,因为是要求挑选出的物品总重量必须不能超过
W 的物品的重量。当然了,对于没有挑选出来的,根本也就不存在价值的可能。不用相加。 - 对于递归其实在某种意义上市一种循环,只是循环的条件有所不同。