题目意思很明确,将给定的物品分成两部分,使得这两部分的和的绝对值之差最小。出看题目,想分成每块硬币放入0号和1号盒子,的最小值,但是发现需要有很多的状态需要记录,随重叠,但是无法存储得下,故放弃。考虑用背包容量为总和的一半来存放硬币,使得该背包所能装下的硬币之和最大,硬币的耗费为其值,硬币的价值也为其值。这样问题就转变为01背包问题。代码如下:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
using namespace std ;
const int maxn = 30000 ;
int dp[maxn][105] ;
int num[105] ;
int main()
{
int test ;
int n ;
int sum ;
int nsum ;
int i ;
int j ;
cin>>test ;
while(test--)
{
cin>>n ;
nsum = 0 ;
for(i = 1 ; i <= n ; i ++)
{
cin>>num[i] ;
nsum += num[i] ;
}
sum = nsum / 2 ;
memset(dp , 0 , sizeof(dp)) ;
for(i = 1 ; i <= n ; i ++)
{
for(j = sum ; j >= 0 ; j --)
{
dp[i][j] = dp[i-1][j] ;
if(j >= num[i])
dp[i][j] = max(dp[i-1][j] , dp[i-1][j-num[i]] + num[i] ) ;
}
}
cout<<abs(nsum - dp[n][sum] - dp[n][sum])<<endl ;
}
return 0 ;
}