AcWing 487. 金明的预算方案(分组背包)

题目链接:点击这里

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

每一组主件与附件可以看成一个物品组,每组有 n n 个附件就有 2 n 2^n 个物品(决策),并且同一组内的物品(决策)最多只能选一个。

#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
typedef pair<int, int> PII;
const int N = 60, M = 32010;

int n, m;
PII a[N];           // 主件
vector<PII> b[N];   // 附件
int f[M];

int main()
{
    cin >> m >> n;      // m是背包容量,n是物品个数

    for (int i = 1; i <= n; i ++ )  //把n个物品进行分组
    {
        int v, p, q;
        cin >> v >> p >> q;
        p *= v;
        if(!q)  a[i] = {v, p};
        else    b[q].push_back({v, p});
    }

    for (int i = 1; i <= n; i ++ )          // 枚举每一个物品组
    {
        for (int u = m; u >= 0; u -- )      // 再逆序枚举体积
        {
            for (int j = 0; j < 1 << b[i].size(); j ++ )  // 再枚举决策
            {
                int v = a[i].first, w = a[i].second;
                
                for (int k = 0; k < b[i].size(); k ++ )  // 二进制表示出所有决策
                {
                    if (j >> k & 1)
                    {
                        v += b[i][k].first;
                        w += b[i][k].second;
                    }
                }
                
                if (u >= v) f[u] = max(f[u], f[u - v] + w);
            }
        }
    }

    cout << f[m] << endl;

    return 0;
}
发布了822 篇原创文章 · 获赞 127 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/104976403
今日推荐