您的位置:首页 > 其它

51nod 多重背包问题

2016-08-04 17:37 141 查看
100%

多重背包问题

一个背包,承量有限为W,有n种物体,第i种物体,价值Vi,占用重量为 Wi,且有Ci件,选择物品若干放入背包,使得总重量不超过背包的承重。总价值最大?

输入

第1行,2个整数,N和W中间用空格隔开。N为物品的种类,W为背包的容量。(1 <= N <= 100,1 <= W <= 50000)

第2 - N + 1行,每行3个整数,Wi,Pi和Ci分别是物品体积、价值和数量。(1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)

输出

输出可以容纳的最大价值。

输入示例

3 6

2 2 5

3 3 8

1 4 1

输出示例

9

很久以前写的,不建议用这个方法,懒得改,直接给链接好了点我点我

按照方法二的话会超时的,所以用第三种方法比较不错,1 2 4 8 16 。。。这些个数组和起来可以构成任意数,所以把num[i]拆分成这几个数就好了,然后就是0-1背包的问题了

#include <cstdio>
#include <cstring>
#define LL long long
#define M 100010
#define INF 0x3f3f3f
#define RCL(a, b) memset(a, b, sizeof(a))

int max(int a, int b)
{
return a > b ? a : b;
}
LL min(LL a, LL b)
{
return a < b ? a : b;
}
LL dp[M], b[M], fee2[M], v2[M];
int main()
{
int n, w, v[M], fee[M], num[M];
RCL(dp, 0);
scanf("%d%d", &n, &w);
for(int i=1; i<=n; i++)
{
scanf("%d%d%d", &v[i], &fee[i], &num[i]);
}
int yn = 1;//记录拆分后的背包个数
for(int i=1; i<=n; i++)//麻烦的拆分
{
int k = 1, an = 0;
while(num[i] - k > 0)
{
num[i] -= k;
b[an++] = k;
k *= 2;
}
b[an++] = num[i];
for(int j=0; j<an; j++)
{
v2[yn] = v[i] * b[j];
fee2[yn++] = fee[i] * b[j];
}
}
for(int i=1; i<yn; i++)
{
for(int j=w; j>=v2[i]; j--)
{
dp[j] = max(dp[j], dp[j-v2[i]] + fee2[i]);
}
}
printf("%lld\n", dp[w]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: