题解 | 【模板】多重背包

【模板】多重背包

https://www.nowcoder.com/practice/8fa10063d33a43dd9652c1511a34d461

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 二进制拆分函数 - 使用 long long 避免溢出
vector<pair<long long, long long>> binarySplit(int weight, int value,
int count) {
    vector<pair<long long, long long>> items;  // 存放拆分后的各组物品

    int k = 1;  // 当前要打包的件数:1,2,4,8,...

    while (k <= count) {
        // 把k件物品打包成一组 - 强制转为long long避免溢出
        items.push_back({(long long)k * weight, (long long)k * value});

        // 减去已处理的件数
        count -= k;

        // 准备下一次打包更多件
        k = k * 2;
    }

    // 处理剩余不够2的幂次的件数
    if (count > 0) {
        items.push_back({(long long)count * weight, (long long)count * value});
    }

    return items;
}

int main() {
    int T;
    cin >> T;

    while (T--) {
        int n, m;
        cin >> n >> m;

        vector<long long> dp(m + 1, 0);
        long long baseValue = 0;  // 体积为0的物品的总价值 - 改为long long

        for (int i = 0; i < n; i++) {
            int w, v, s;
            cin >> w >> v >> s;

            // 特殊情况:体积为0
            if (w == 0) {
                baseValue += (long long)s * v;  // 强制转为long long
                continue;
            }

            // 1. 二进制拆分
            auto items = binarySplit(w, v, s);

            // 2. 对每组做0-1背包
            for (auto& item : items) {
                long long weight = item.first;   // 改为long long
                long long value = item.second;   // 改为long long

                // 0-1背包(逆序)
                for (int j = m; j >= weight; j--) {
                    dp[j] = max(dp[j], dp[j - weight] + value);
                }
            }
        }

        // 最终结果 = 背包能装的最大价值 + 体积为0的物品的总价值
        cout << dp[m] + baseValue << endl;
    }

    return 0;
}

全部评论

相关推荐

03-08 18:11
门头沟学院 Java
想要实习的牛:这么牛逼的简历都吃瘪吗🌚那我不寄了
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务