<center>
提交: 20 解决: 5
</center>
1017: 最小差
时间限制: 1 Sec 内存限制: 128 MB提交: 20 解决: 5
</center>
题目描述
假设有n个正整数a1,a2,a3…an,希望将这些数分成两组,使得两组的和差值最小。
输入
第一行输入整数m(0<m<=100),代表测试用例的数量。
接下来每个用例由两行组成,第一行是一个整数n(1<n<=100),表示整数的个数,第二行包含n个正整数,且最大不超过100。
输出
输出最小的差的绝对值。
样例输入
263 2 3 4 2 951 1 1 1 10
样例输出
16
提示
来源
思路:
题意很清楚,n个数,分两组,两组的差最接近0。很自然的想到这是在类似于取东西,看怎么取得平均(就是说要使两组数都尽可能的接近sum/2)。所以只需要对一组进行求算使它最接近sum/2,那样的话另一组自然也是最接近的。这就是典型的01背包问题了,sum/2的体积求最多可以装多少。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int v[100+2];
int dp[100+2][100+2];
int main()
{
//freopen("in.txt","r",stdin);
int m;
cin>>m;
while(m--)
{
int n;
scanf("%d",&n);
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
sum+=v[i];
}
int summ=sum/2;
memset(dp,0,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=summ;j>=0;j--)
{
if(j>=v[i])dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+v[i]);
else dp[i][j]=dp[i-1][j];
}
printf("%d\n",abs(sum-2*dp[n][summ]));
}
}