又见01背包
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W的物品,求所有挑选方案中物品价值总和的最大值。1 <= n <=1001 <= wi <= 10^71 <= vi <= 1001 <= W <= 10^9
-
输入
-
多组测试数据。
每组测试数据第一行输入,n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。
输出
- 满足题意的最大价值,每组测试数据占一行。 样例输入
-
4 5 2 3 1 2 3 4 2 2
样例输出
-
7
-
多组测试数据。
这题的问题与不同的背包问题没什么差别,但是数据达到10^9,数组开不了那么大。
因为1 <= n <=100 1 <= vi <= 100, 所以所有物品最大的价值是10000,这个数值数组完全没问题,所以01背包问题的价值和重量调换一下位置。
dp[ i ]就表示总价值为 i 的物品的重量的最小值,dp[ i ] = min{dp[ i ], dp[i - v[i]] + w[i]} (在选不选第 i 件物品里面选择重量小的)
还要注意dp数组要初始化为一个很大的值,因为我第一次值初始化为99999999,所以WA了
#include <stdio.h>
#include <string.h>
int dp[10010];
int w[110], v[110];
int main (void)
{
int n, W, s;
while(scanf("%d %d", &n, &W) != EOF)
{
s = 0;
int i, j;
for(i = 0; i < n; i++)
{
scanf("%d %d", &w[i], &v[i]);
s += v[i];
}
for(i = 0; i <= s; i++)
{
dp[i] = 999999999;
}
dp[0] = 0;
for(i = 0; i < n; i++)
{
for(j = s; j >= v[i]; j--)
{
dp[j] = dp[j] < dp[j - v[i]] + w[i] ? dp[j] : dp[j - v[i]] + w[i];
}
}
for(i = s; i >= 0; i--)
{
if(dp[i] <= W)
{
printf("%d\n", i);
break;
}
}
}
return 0;
}