您的位置:首页 > 其它

zzuoj 10452: "分"数 【dp】

2016-04-10 11:33 190 查看
题目链接: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: