HJ16 购物单
分组背包。
因为物品和物品之间存在依附关系,不如将这些物品归位一类(用dfs_create找出这一类),在这一类中挑选出其中一个拿出来当一个物品,纳入到DP的过程中。
分组背包需要注意的是,DP过程中内外层循环的安排。
for(int V=N;V>=0;V--){
for(int j=0;j<new_groups[i].size();j++){
auto [cost_0,val_0] = new_groups[i][j];
if(V>=cost_0) dp[V] = max(dp[V],dp[V-cost_0]+val_0);
}
}
代码如下:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int N0 = 65;
int bel[N0];
int cost[N0];
int val[N0];
vector<tuple<int,int,int> > groups[N0];
vector<tuple<int,int> > new_groups[N0];
void dfs_create(int i,int pos,int curCost,int curVal){
if(pos>=int(groups[i].size())) return ;
auto [cost,val,id] = groups[i][pos];
if(id==i){
dfs_create(i, pos+1, curCost, curVal);
return ;
}
new_groups[i].push_back(tuple<int,int>{curCost+cost,curVal+cost*val});
dfs_create(i, pos+1, curCost, curVal);
dfs_create(i, pos+1, curCost+cost, curVal+cost*val);
return ;
}
int dp[32005];
int main() {
int N,m;
cin>>N>>m;
for(int i=1;i<=m;i++){
cin>>cost[i]>>val[i]>>bel[i];
int id = bel[i]==0?i:bel[i];
groups[id].push_back(tuple<int,int,int>{cost[i],val[i],i});
}
for(int i=1;i<=m;i++){
if(groups[i].size()==0) continue;
new_groups[i].push_back(tuple<int,int>{cost[i],cost[i]*val[i]});
dfs_create(i,0,cost[i],cost[i]*val[i]);
}
for(int i=1;i<=m;i++){
if(new_groups[i].size()==0) continue;
for(int V=N;V>=0;V--){
for(int j=0;j<new_groups[i].size();j++){
auto [cost_0,val_0] = new_groups[i][j];
if(V>=cost_0) dp[V] = max(dp[V],dp[V-cost_0]+val_0);
}
}
}
cout<<dp[N];
return 0;
}