题目描述:
一个数组中有若干正整数,将此数组划分为两个子数组,使得两个子数组各元素之和a,b的差最小,对于非法输入应该输出ERROR。
输入:
数组中的元素
输出:
降序输出两个子数组的元素和
样例输入:
10 20 30 10 10
10 20 abc 10 10
样例输出:
40 40
ERROR
实现代码:
#include<cstdio>
#include<string>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 1e3 + 10;
string str;
int data[maxn];
int strToArray(int &sum) {
memset(data, 0, sizeof(data));
int num = 0;
for(int i = 0; i < str.size(); i++) {
if(str[i] >= '0' && str[i] <= '9') {
data[num] = data[num] * 10 + str[i] - '0';
} else if(str[i] == ' ') {
sum += data[num];
num++;
} else {
return 0;
}
}
sum += data[num];
num++;
return num;
}
//dfs函数用于贪心算法,每次取或者不取该数,使最终结果最接近half或者等于half(注意最终结果一定小于等于half)
void dfs(int index, int ans, int half, int num, int &res) {
if(index == num) {
return;
}
if(ans + data[index] <= half) {
res = max(res, ans + data[index]);
if(res == half) {
return;
}
dfs(index + 1, ans + data[index], half, num, res);
}
dfs(index + 1, ans, half, num, res);
}
int main() {
while(getline(cin, str)) {
int sum = 0;
int num = strToArray(sum);
if(num == 0) {
printf("ERROR\n");
continue;
}
int res = 0;
dfs(0, 0, sum / 2, num, res);
printf("%d %d\n", sum - res, res);
}
return 0;
}
/*
此题用动态规划解决0-1背包问题会导致数组越界,因此可以采用贪心算法来解决。
由于要求俩个子数组差值最小,那么要么俩子数组相等,要么一个略大于总和的一半,一个略小于
*/