题解 | #数组分组#
数组分组
https://www.nowcoder.com/practice/9af744a3517440508dbeb297020aca86
#include <deque>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
deque<int>
que; // que里面前面全是5的倍数,后面全是非5 3 的倍数
int sum = 0;
int pos = 0;
int sumFive = 0;
while (n--) {
int i;
cin >> i;
if (i % 15 == 0 &&
i != 0) { // 3 5的公倍数不能被分进任意一组 判断整除时永远要先讨论0!!!
cout << "false";
return 0;
}
// 若没有5的倍数, pos = 0;
if (i % 5 == 0 && i != 0) { // 5的倍数从前面压进去
que.push_front(i);
sumFive += i;
pos++;
} else if (i % 3 != 0 || i == 0) { // 非5 3 的倍数从后面压进去
que.push_back(i);
}
sum += i;
}
if (sum % 2 != 0 && sum != 0) { // sum是奇数,肯定分不出来
cout << "false";
return 0;
}
vector<int> nums;
while (!que.empty()) {
nums.push_back(que.front());
que.pop_front();
}
sum /= 2;
sum -= sumFive;
sum += 25000;
vector<int> dp(50000, 0); // dp[25000]对应 sum = 0
dp[25000] = 1;
int minIdx = 25000; // 需要记录一个能达到的最小数
for (int i = pos; i < nums.size(); i++) {
if (nums[i] >= 0) {
for (int j = 50000; j >= nums[i] + minIdx;
j--) {
if (dp[j - nums[i]] == 1) {
dp[j] = 1;
// if (j < minIdx) minIdx = j;
}
}
} else {
for (int j = 0; j <= nums[i] + minIdx; j++) {
if (dp[j - nums[i]] == 1) {
dp[j] = 1;
if (j < minIdx) minIdx = j; // 更新最小idx
}
}
}
}
cout << (dp[sum] == 1 ? "true" : "false");
}
// 64 位输出请用 printf("%lld")
双向动态规划。
查看14道真题和解析
