金明的预算方案(01背包的变式)

在这里插入图片描述
带有附件的背包问题,它属于01背包的变式
每一个物品最多只有两个附件,那么我们在对主件进行背包的时候,决策就不再是两个了,而是五个。
01背包的决策是:
1.不选,然后去考虑下一个
2.选,背包容量减掉那个重量,总值加上那个价值。

这个题的决策是五个,分别是:
1.不选,然后去考虑下一个
2.选且只选这个主件
3.选这个主件,并且选附件1
4.选这个主件,并且选附件2
5.选这个主件,并且选附件1和附件2

我们知道,01背包的状态转移方程(已使用滚动数组优化)是f[j] = max(f[j],f[j-w[i]]+c[i]),那么,这道题的转移方程也就不难写出了。

不选附件的①:f[j] = max(f[j],f[j-v0[i]]+w0[i]);

选附件1的②:f[j] = max(f[j],f[ j - v0[i] - v1[i] ] + w0[i] + w1[i]);

选附件2的③:f[j] = max(f[j],f[ j - v0[i] - v2[i] ] + w0[i] + w2[i]);

选附件1和附件2的④:f[j] = max(f[j],f[ j - v0[i] - v1[i] - v2[i] ] + w0[i] + w1[i] + w2[i]);

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
const int N = 4 * 1e4 + 5;

typedef struct Node{
    int v,p,q;
}Node;
Node node[65];
pair<int,int> a[65][4];
int dp[N];
int n,m;

int main()
{
    scanf("%d %d",&n,&m);
    for(int i = 1;i <= m;++i){
        scanf("%d %d %d",&node[i].v,&node[i].p,&node[i].q);
    }
    memset(a,-1,sizeof(a));
    for(int i = 1;i <= m;++i){
        if(node[i].q == 0){
            a[i][0].fi = node[i].v;
            a[i][0].se = node[i].v * node[i].p;
        }else{
            int cnt = 1;
            if(a[node[i].q][cnt].fi != -1) cnt++;
            a[node[i].q][cnt].fi = node[i].v;
            a[node[i].q][cnt].se = node[i].v * node[i].p;
        }
    }
    memset(dp,0,sizeof(dp));
    int MAX = -1;
    for(int i = 1;i <= m;++i){
        if(node[i].q == 0){
            for(int j = n;j >= 0;--j){
                if(j - a[i][0].fi >= 0)
                    dp[j] = max(dp[j],dp[j - a[i][0].fi] + a[i][0].se);
                if(a[i][1].fi != -1 && j - a[i][0].fi - a[i][1].fi >= 0)
                    dp[j] = max(dp[j],dp[j - a[i][0].fi - a[i][1].fi] + a[i][0].se + a[i][1].se);
                if(a[i][2].fi != -1 && j - a[i][0].fi - a[i][2].fi >= 0)
                    dp[j] = max(dp[j],dp[j - a[i][0].fi - a[i][2].fi] + a[i][0].se + a[i][2].se);
                if(a[i][1].fi != -1 && a[i][2].fi != -1 && j - a[i][0].fi - a[i][1].fi - a[i][2].fi >= 0)
                    dp[j] = max(dp[j],dp[j - a[i][0].fi - a[i][1].fi - a[i][2].fi] + a[i][0].se + a[i][1].se + a[i][2].se);
                MAX = max(MAX,dp[j]);
            }
        }
    }
    printf("%d\n",MAX);
    return 0;
}

发布了269 篇原创文章 · 获赞 33 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/96968179