HDU_1171

    这个题目可以用生成函数的思路去做,也可以用多重背包的思路去做,而且用多重背包的思路做时可以参考《背包九讲》里面的二进制优化多重背包问题那一块,这样做效率更高。

    另外多重背包问题用单调队列优化之后还可以达到O(VN)的效果,我暂时还没有学,所以就只写了这个二进制优化的版本。

//生成函数
#include<stdio.h>
#include<string.h>
#define MAXD 60
#define MAXM 130000
int N, S, M, value[MAXD], num[MAXD], wa[MAXM], wb[MAXM], *a, *b;
void init()
{
int i, j, k;
S = 0;
for(i = 1; i <= N; i ++)
{
scanf("%d%d", &value[i], &num[i]);
S += value[i] * num[i];
}
M = S / 2;
}
void solve()
{
int i, j, k, *t;
a = wa, b = wb;
memset(b, 0, sizeof(b[0]) * (M + 1));
b[0] = 1;
for(i = 1; i <= N; i ++)
{
memset(a, 0, sizeof(a[0]) * (M + 1));
for(j = 0; j <= num[i]; j ++)
for(k = 0; k + value[i] * j <= M; k ++)
a[k + value[i] * j] += b[k];
t = a, a = b, b = t;
}
for(i = M; i > 0; i --)
if(b[i])
break;
printf("%d %d\n", S - i, i );
}
int main()
{
for(;;)
{
scanf("%d", &N);
if(N < 0)
break;
init();
solve();
}
return 0;
}

 

//多重背包
#include<stdio.h>
#include<string.h>
#define MAXD 500
#define MAXM 130000
int N, M, S, X, value[MAXD], wa[MAXM], wb[MAXM], *a, *b, elem[] = {1, 2, 4, 8, 16, 32, 64, 128};
void init()
{
int i, j, k, v, n;
X = S = 0;
for(i = 0; i < N; i ++)
{
scanf("%d%d", &v, &n);
S += v * n;
for(j = 0; n - elem[j + 1] + 1 > 0; j ++)
value[X ++] = elem[j] * v;
value[X ++] = (n - elem[j] + 1) * v;
}
M = S / 2;
}
void solve()
{
int i, j, k, *t;
a = wa, b = wa;
memset(b, 0, sizeof(b[0]) * (M + 1));
for(i = 0; i < X; i ++)
{
for(j = 0; j <= M; j ++)
{
a[j] = b[j];
if(j >= value[i] && b[j - value[i]] + value[i] > a[j])
a[j] = b[j - value[i]] + value[i];
}
t = a, a = b, b = t;
}
printf("%d %d\n", S - b[M], b[M]);
}
int main()
{
for(;;)
{
scanf("%d", &N);
if(N < 0)
break;
init();
solve();
}
return 0;
}



posted on 2012-03-06 15:25  Staginner  阅读(235)  评论(0编辑  收藏  举报