hdu1171: Big Event in HDU

hdu1171: http://acm.hdu.edu.cn/showproblem.php?pid=1171
题意:给定设备种类n,接下来输出n行,v[i]、m[i]表示有m[i]个价值为v[i]的设备,求将这些设备分为两部分,每部分的价值,要求两部分的价值相差最小。 解法:混合背包,背包最大容量为总价值sum的一半s,要求价值尽量大,则f[s]和sum-f[s]即为答案。
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int v[100],m[100],f[1000000];
int max(int a,int b)
{
    if(a>b)
        return a;
    else
        return b;
}
int main()
{
    int n,i,j,s,a,b,sum;
    while(1)
    {
        s=0;sum=0;
        memset(f,0,sizeof(f));
        scanf("%d",&n);
        if(n<0)
            break;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&v[i],&m[i]);
            sum=sum+v[i]*m[i];
        }
        s=sum/2;
        for(i=0;i<n;i++)
        {
            if(m[i]==1)                   //01背包 
            {
                for(j=s;j>=v[i];j--)
                    f[j]=max(f[j-v[i]]+v[i],f[j]);
            }
            else if(m[i]*v[i]>=s)           //完全背包 
            {
                for(j=v[i];j<=s;j++)
                    f[j]=max(f[j-v[i]]+v[i],f[j]);
            } 
            else                           //多重背包 
            {
                for(int k=1;m[i]>k;k=k*2)
                {
                    for(j=s;j>=v[i]*k;j--)
                        f[j]=max(f[j-v[i]*k]+v[i]*k,f[j]);
                    m[i]=m[i]-k;
                }
                for(j=s;j>=m[i]*v[i];j--)
                    f[j]=max(f[j-v[i]*m[i]]+v[i]*m[i],f[j]);
            }
        }
        a=max(f[s],sum-f[s]);
        b=sum-a;
        printf("%d %d\n",a,b);
    }
}
/*input:
2
10 1
20 1
3
10 1 
20 2
30 1
-1
output:
20 10
40 40
*/

posted on 2012-07-26 11:56  acmer-jun  阅读(149)  评论(0编辑  收藏  举报

导航