您的位置:首页 > 其它

UVA 562 Dividing coins

2012-04-09 16:50 176 查看
题目大意:给你若干硬币,让你分成两份,使其绝对值之差尽量的小。

很容易想到,我们需要枚举出这些硬币可能凑出的所有面值,那么,怎么去算出这些硬币可能凑出的面值就是我们需要解决的问题了。

令dp[i]数组来保存是否可以凑出i的面值的结果。可以为1,否则为0.sum为这些硬币的面值之和。

显然dp[0]=1,有一份一分钱都没有事肯定可以的。那么dp[sum]=1,有一份可以囊括所有的硬币。

那么既然dp[0]是可以的,那么dp[0+coin[j]]也一定可以凑出来,同理dp[sum-coin[j]]也是可以的;如此推广下去,dp[coin[j]]可以,dp[coin[j]+coin[k]]也可以………………我们获得的可以凑出来的面值数量会越来越多。这样的算法复杂度为n的平方吧。

最后,我们去寻找距离总面值数一半的(sum/2)差值最小的那个数j,那么我们最后输出的结果显然是sum-j*2。

下面贴代码

View Code

#include <iostream>
#include <cstring>
using namespace std;
int coin[101];
int dp[101000];
int main()
{
int ncase,sum,i,j,m;
cin>>ncase;
while(ncase--)
{
memset(dp,0,sizeof(dp));
sum = 0;
cin>>m;
for(i = 1;i <= m;i++)
{
cin>>coin[i];
sum += coin[i];
}
dp[0] = 1;
for(i = 1;i <= m;i++)
for(j = sum;j >= coin[i];j--)
if(dp[j - coin[i]])
dp[j] = 1;
for(i = sum / 2;i >= 0;i--)
if(dp[i])
{
j = i;
break;
}
/*for(i = 0;i <= sum;i++)
cout<<i<<"->"<<dp[i]<<" ";
cout<<endl;*/
cout<<sum - 2 * j<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: