题意是说
学院分家, 所以需要分财产 ,给出N表示——N个财产,然后接下来N行 ,每行两个数 ,一个表示该财产的价值,另一个表示数量,最后需要求的是怎么分财产,才能让两个学院所分的财产最接近。
其实就是个01背包,但是刚开始看的时候不知道怎么练习到01背包,毕竟是要求两个学院分到的财产价值差距最小,所以无从下手。
但是后面想到可以对所有财产的总价值进行使用01背包,但是发现还是不对劲。
最后终于想到了对总财产的一半进行背包处理。只需要考虑其中一个学院,让其分到财产的价值接近总价值的一半。然后还有个要处理的地方就是财产的数量不一定是1,我的处理是把数量超过一定财产分出来,做为一个新的财产。
后面看了下其他人的做法,发现用了母函数,这个我还是不怎么知道,待我去看一发。。。。
代码很简单:
#include <stdio.h>
#define max(a,b) a>b?a:b
int main()
{
freopen("in.in","r",stdin);
int N;
while(scanf("%d",&N)!=EOF&&(N>0))
{
int sum=0;
int v[55100],m[110];
int i;
for( i=1;i<=N;i++)
{
scanf("%d %d",&v[i],&m[i]);
sum+=v[i]*m[i];
}
// 把同价格的物品分开
for(int j=1;j<=N;j++)
{
if(m[j]>1)
{
for(int k=1;k<m[j];k++)
{
v[i++]=v[j];
}
}
}
//for(int j=1;j<i;j++)printf("%d\n",v[j] );
int temp=sum/2;
int dp[25500];
for(int j=0;j<25500;j++)dp[j]=0;
for(int j=1;j<i;j++)
{
for(int k=temp;k>=v[j];k--)
{
dp[k]=max(dp[k],dp[k-v[j]]+v[j]);
}
}
int maxn=0;
maxn=sum-dp[temp];
if(maxn>dp[temp])
printf("%d %d\n",maxn,dp[temp]);
else
printf("%d %d\n",dp[temp],maxn );
}
return 0;
}