您的位置:首页 > 其它

hdu1171: Big Event in HDU

2012-07-26 11:56 232 查看
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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: