这是一个背包类型的问题,但是存在附件这个问题,因为要拿附件就一定要拿主件,而且附件最多只有2种,假设有2种附件,那么这个物品就有三种状态
第一种就是只拿主键,dp[j] = max(dp[j], dp[j-now[i].v] + now[i].v*now[i].p);
第二种就是那主键和第一个附件 dp[j] = max(dp[j], dp[j-now[i].v-vec[i][0].v] + now[i].v*now[i].p+vec[i][0].v*vec[i][0].p);
第三种就是拿主键和第二个附件,基本同上。
第四种就是拿主键和两个附件,dp[j] = max(dp[j], dp[j-now[i].v-vec[i][0].v-vec[i][1].v]+now[i].v*now[i].p+vec[i][1].v*vec[i][1].p+vec[i][0].v*vec[i][0].p);
然后按照背包问题的转移方式做就可以了,滚动一下优化空间,代码如下。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e2 + 10;
int dp[maxn*1000],v[maxn][4],val[maxn],q[maxn],a[maxn];
struct node {
int q,v,p;
}now[maxn];
vector<node> vec[maxn];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for (int i=1; i<=m; i++) {
cin >> now[i].v >> now[i].p >> now[i].q;
if (now[i].q != 0) {
vec[now[i].q].push_back(now[i]);
}
}
for (int i=1; i<=m; i++) {
if (now[i].q == 0) for (int j=n; j>=0; j--){
if (j >= now[i].v)
dp[j] = max(dp[j], dp[j-now[i].v] + now[i].v*now[i].p);
if (vec[i].size() >= 1 && j >= now[i].v + vec[i][0].v)
dp[j] = max(dp[j], dp[j-now[i].v-vec[i][0].v] + now[i].v*now[i].p+vec[i][0].v*vec[i][0].p);
if (vec[i].size() >= 2 ){
if (j >= now[i].v + vec[i][1].v)
dp[j] = max(dp[j], dp[j-now[i].v-vec[i][1].v]+now[i].v*now[i].p+vec[i][1].v*vec[i][1].p);
if (j >= now[i].v + vec[i][0].v + vec[i][1].v)
dp[j] = max(dp[j], dp[j-now[i].v-vec[i][0].v-vec[i][1].v]+now[i].v*now[i].p+vec[i][1].v*vec[i][1].p+vec[i][0].v*vec[i][0].p);
}
}
}
cout << dp[n] << endl;
return 0;