传送门:牛客
题目描述:
题目较长,此处省略
输入:
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
输出:
2200
这道题应该可以说是这道题的升级版,也算一道 01 背包的题目 01背包的题目 01背包的题目,但是是背包的变种,暂且称之为有依赖的背包吧
主要思路:
- 虽然这道题刚开始看题觉得一头雾水,但是当我们仔细分析一下之后这道题还是可做的.我们只要在我们的01背包的思想上面改一下即可.我们当时做01背包时是怎么做的,是不是对于一个物品有两种决策状态(要么我们选取这个物品,要么不选),那么现在我们只不过多了三种决策而已,分别是对于一个附属品,我们只能在有主件的情况下才只能选择,因此我们只要枚举我们的主件即可,对于我们的附件.在枚举我们的主件时,假设我们的体积足够,然后随着主件一起减去体积,一起加上价值,因此有选取主件+附件1,主件+附件2,主件+附件1+附件2这三种决策,我们只要在我们的01背包的模板中添加即可(但是注意我们只需枚举主件)
注意:我们此题需要使用long long
下面是具体的代码部分:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
#include <deque>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x=0,w=1;char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*w;
}
#define maxn 1000000
#define ll_maxn 0x3f3f3f3f3f3f3f3f
const double eps=1e-8;
int n,m;
struct Thing{
ll w,v,flag;
}zhujian[maxn],fujian[maxn][3];
ll num[maxn];ll dp[maxn];
int main() {
n=read();m=read();
ll v,p,q;
for(int i=1;i<=m;i++) {
v=read();p=read();q=read();
if(q==0) {
zhujian[i].w=p*v;
zhujian[i].v=v;
zhujian[i].flag=1;
}else {
num[q]++;
fujian[q][num[q]].w=p*v;
fujian[q][num[q]].v=v;
}
}
for(int i=1;i<=m;i++) {
if(zhujian[i].flag==0) continue;
for(int j=n;j>=zhujian[i].v;j--) {
dp[j]=max(dp[j],dp[j-zhujian[i].v]+zhujian[i].w);
if(j>=zhujian[i].v+fujian[i][1].v){
dp[j]=max(dp[j],dp[j-zhujian[i].v-fujian[i][1].v]+zhujian[i].w+fujian[i][1].w);
}
if(j>=zhujian[i].v+fujian[i][2].v){
dp[j]=max(dp[j],dp[j-zhujian[i].v-fujian[i][2].v]+zhujian[i].w+fujian[i][2].w);
}
if(j>=zhujian[i].v+fujian[i][1].v+fujian[i][2].v) {
dp[j]=max(dp[j],dp[j-zhujian[i].v-fujian[i][1].v-fujian[i][2].v]+fujian[i][1].w+fujian[i][2].w+zhujian[i].w);
}
}
}
cout<<dp[n]<<endl;
return 0;
}