题意:
有n个钱币,每个的币值可能各不相同,要求把钱币分成两堆,使两堆的价值差尽可能小。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<climits>
#include<queue>
#include<vector>
#include<map>
#include<sstream>
#include<set>
#include<stack>
#include<cctype>
#include<utility>
#pragma comment(linker, "/STACK:102400000,102400000")
#define PI (4.0*atan(1.0))
#define eps 1e-10
#define sqr(x) ((x)*(x))
#define FOR0(i,n) for(int i=0 ;i<(n) ;i++)
#define FOR1(i,n) for(int i=1 ;i<=(n) ;i++)
#define FORD(i,n) for(int i=(n) ;i>=0 ;i--)
#define lson ind<<1,le,mid
#define rson ind<<1|1,mid+1,ri
#define MID int mid=(le+ri)>>1
#define zero(x)((x>0? x:-x)<1e-15)
#define mk make_pair
#define _f first
#define _s second
using namespace std;
//const int INF= ;
typedef long long ll;
//const ll inf =1000000000000000;//1e15;
//ifstream fin("input.txt");
//ofstream fout("output.txt");
//fin.close();
//fout.close();
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
const int INF =0x3f3f3f3f;
const int maxn=120 ;
//const int maxm= ;
int n,tot;
int val[maxn];
int dp[maxn*500];
/*
tot是一定的,
如果某个值x能够到达,那么tot-x一定能到达
只用从i=tot/2 逐渐减小 开始检查 是否i和tot-i都能到达
*/
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
tot=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&val[i]),tot+=val[i];
memset(dp,-1,sizeof dp);
dp[0]=0;
for(int i=1;i<=n;i++)
{
int va=val[i];
for(int v=tot;v>=va;v--)
{
if(dp[v-va]==-1) continue;//当初这里掉了-1,没有考虑dp[v-va]是不可达的
dp[v]= max(dp[v-va]+va,dp[v]);
}
}
int st=tot/2;
for( ;st>=0;st--)
{
if(dp[st]!=-1) {printf("%d\n",tot-st-st);break;}
}
}
return 0;
}