HDU 1171 Big Event in HDU (多重背包)

来源:互联网 发布:java往word中写入文本 编辑:程序博客网 时间:2024/06/16 06:17

Problem Description

两堆物品,a[i]物品有b[i]件价值为c[i],求划分为两堆时各个堆的价值。

Sample Input

2
10 1
20 1
3
10 1
20 2
30 1
-1

Sample Output

20 10
40 40

Solution

多重背包转换为01背包和完全背包

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 300010;int dp[N];int v[110], num[110];int n;void ZeroOnePack(int w, int v, int W){    for (int i = W; i >= w; i--)        dp[i] = max(dp[i], dp[i - w] + v);}void CompletePack(int w, int v, int W){    for (int i = w; i <= W; i++)        dp[i] = max(dp[i], dp[i - w] + v);}void MultiplePack(int w, int v, int num, int W){    if (w * num >= W)        CompletePack(w, v, W);    else    {        int k = 1;        while (k <= num)        {            ZeroOnePack(k * w, k * v, W);            num -= k;            k *= 2;        }        ZeroOnePack(num * w, num * v, W);    }}int main(){    while (scanf("%d", &n), n >= 0)    {        int W = 0;        for (int i = 1; i <= n; i++)            scanf("%d%d", &v[i], &num[i]), W += v[i] * num[i];        memset(dp, 0, sizeof dp);        for (int i = 1; i <= n; i++)            MultiplePack(v[i], v[i], num[i], W / 2);        int a = dp[W / 2], b = W - a;        if (a < b)            swap(a, b);        printf("%d %d\n", a, b);    }    return 0;}
原创粉丝点击