题目链接:zzuoj 10452: “分”数
10452: “分”数
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 111 Solved: 20
[Submit][Status][Web Board]
Description
有一个由偶数个正整数组成的无序数组,现在小D想:怎样把这个含有偶数(2*n)个数的数组分为两个元素个数相等的数组,并使得两个字数组的和最接近?
Input
有多组测试数据。
每组第一行输入一个N(N<=50且N为偶数),代表有多少个数。
接下来输入由空格隔开的N个数x(0<=x<=100)。
Output
输出每行包含两个数,分别代表分割成的两数组的和。(从小到大)
Sample Input
4
1 3 2 4
6
1 3 6 8 2 5
Sample Output
5 5
12 13
dp[i][j][k]
表示前i个数取j个和为k的状态,存在为1,反之为0;
这样写在初始化的时候会T,直接滚动数组优化下。。。
第二维开n/2,第三维开sum / 2即可。
AC代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
#include <cstdlib>
#define fi first
#define se second
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MOD = 1e9 + 7;
const int MAXN = 100;
const int INF = 1e9 + 10;
void add(LL &x, LL y) { x += y; x %= MOD; }
int a[51];
int dp[2][26][3000];
int main()
{
int n;
while(scanf("%d", &n) != EOF) {
int sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum += a[i];
}
CLR(dp, 0); bool last = 1;
dp[last][0][0] = 1; dp[last][1][a[1]] = 1;
for(int i = 2; i <= n; i++) {
int now = !last;
for(int j = 0; j <= n / 2; j++) {
for(int k = 0; k <= sum / 2; k++) {
dp[now][j][k] = dp[last][j][k];
if(k >= a[i] && j >= 1) {
dp[now][j][k] |= dp[last][j-1][k-a[i]];
}
}
}
last = !last;
}
int sum1 = -1;
for(int k = sum / 2; k >= 0; k--) {
if(dp[last][n/2][k]) {
sum1 = k;
break;
}
}
printf("%d %d\n", sum1, sum - sum1);
}
return 0;
}