题解 | #数组分组#

数组分组

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")

双向动态规划。

全部评论

相关推荐

牛客鼠:校友你这简历基本无敌了,春招刷刷题去冲大厂
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务