0
点赞
收藏
分享

微信扫一扫

分组背包(实质)

正义的杰克船长 2022-04-29 阅读 45
c++

分组背包的实质还是组合数问题,只不过有一些限制

多重背包其实是分组背包的一个特殊形式

金明的预算方案

这就是纯粹的分组背包

就是将里面的选择买什么当作一个决策,每组只能选择一种决策请添加图片描述
就比如这里的蓝的代表主件,跟它相连的就是附件
然后每个主件及其附件看成一组,然后找出来有多少个决策,每个决策就是组中的一个情况,就相当于分组背包,每个只能选一种决策

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define PII pair<int, int>
#define x first
#define y second

const int N = 32010;

int n, m;

PII mas[N];
vector<PII> ser[N];
int f[N];
int main()
{
    cin >> m >> n;
    
    for(int i=1; i<=n; i++) 
    {
        int v, w, q;
        cin >> v >> w >> q;
        
        if(!q) mas[i] = {v, v * w};
        else ser[q].push_back({v, v * w});
        
    }
    
    for(int i=1; i<=n; i++)
    {
        if(mas[i].x)//并不是1~n都是主件,有的是附件,上面没有离散化,所以这里就直接看看价值是不是0,是0就跳过
        {
            for(int j = m; j>=0; j--)
            {
                for(int p = 0; p < 1 << ser[i].size(); p++)//2的n次方种策略
                {
                    int v = mas[i].x, w = mas[i].y;
                    for(int q = 0; q < ser[i].size(); q++)//枚举每个附件
                    {
                        if (p >> q & 1)//用二进制来表示有没有
                        {
                            v += ser[i][q].x;
                            w += ser[i][q].y;
                        }
                    
                    }
                    if (j >= v) f[j] = max(f[j], f[j - v] + w);
                }
            }
        }
            
    }
    
    cout << f[m] << endl;
    return 0;
}

开心的金明

01背包

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'

const int N = 30010;

int n, m;
int f[N];

int main()
{
    cin >> m >> n;
    for (int i = 1; i <= n; i ++ )
    {
        int v, w;
        cin >> v >> w;
        w *= v;
        for(int j = m; j>=v; j--)
        {
            f[j] = max(f[j], f[j - v] + w);
        }
    }
    
    cout << f[m] << endl;
    return 0;
}
举报

相关推荐

0 条评论