HJ93 数组分组
dfs/dp
题目描述
输入int型数组,询问该数组能否分成两组,使得两组中各元素加起来的和相等,并且,所有5的倍数必须在其中一个组中,所有3的倍数在另一个组中(不包括5的倍数),能满足以上条件,输出true;不满足时输出false。
本题含有多组样例输入。
输入描述:
第一行是数据个数,第二行是输入的数据
输出描述:
返回true或者false
示例1
输入:
4
1 5 -5 1
3
3 5 8
输出:
true
false
说明:
第一个样例:
第一组:5 -5 1
第二组:1
第二个样例:由于3和5不能放在同一组,所以不存在一种分法。
解题思路
题目说了3的倍数和5的倍数必须放在不同集合,那就先把这部分数组摘出来,然后看剩下的部分能否分配成需要的结果。
这里可以用 dfs 或者 dp,对于要组成的目标和,每个元素要么参与要么不参与,只要有一种方案能达到目标就算成功。
参考代码
注意这里的 v.size() 和 n 含义不同、值不同、更新不同时。
#include <bits/stdc++.h>
using namespace std;
vector<int> v;
// 数组元素能否凑出 target 值
bool dfs(int i, int target) {
if (target == 0) return true;
if (i < 0) return false;
return dfs(i-1, target - v[i])
|| dfs(i-1, target);
}
int main() {
cin.sync_with_stdio(false);
int n;
while (cin >> n) {
v.reserve(n); //
v.resize(0); //
int64_t sumall = 0;
int64_t sum5 = 0; // 5
int64_t sum3 = 0; // 3
for (int i=0; i<n; i++) {
int x;
cin >> x;
sumall += x;
if ((x % 5) == 0) {
sum5 += x;
} else if ((x % 3) == 0) {
sum3 += x;
} else {
v.push_back(x);
}
}
if (sumall % 2) {
cout << "false
";
continue;
}
// printf("sum3=%ld, sum5=%ld, sumall=%ld
", sum3, sum5, sumall);
// for (int x : v) cout << x << ' '; cout << endl;
cout << (dfs(v.size() - 1, sumall / 2 - sum3) ? "true
" : "false
");
}
return 0;
}