P2732 Shopping Offers(DP 状态设计,完全背包基础)
首先发现不让加物品,于是直接放弃那些含有非法物品的套餐,把单物品也当成一个套餐,去跑完全背包即可。
#include<bits/stdc++.h>
using namespace std;
struct node{int cost,types,mark[10],num[10];} a[101];
int n,m,thing[150][6],cnt,need[6],dp[6][6][6][6][6];
unordered_map<int,int> mp;
inline void Min(int &a,int b){a=min(a,b);}
int main(){
//Read
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].types);
for(int j=1;j<=a[i].types;j++)
scanf("%d%d",&a[i].mark[j],&a[i].num[j]);
scanf("%d",&a[i].cost);
}
scanf("%d",&m);
for(int i=1,tmp;i<=m;i++)
scanf("%d%d%d",&tmp,&need[i],&thing[++cnt][0]),thing[cnt][i]=1,mp[tmp]=i;
//To-Thing
for(int i=1,flg;i<=n;i++){
//Check
flg=0;
for(int j=1;j<=a[i].types;j++)
if(!mp.count(a[i].mark[j])||need[mp[a[i].mark[j]]]<a[i].num[j]) flg=1;
if(flg) continue;
//Add
thing[++cnt][0]=a[i].cost;
for(int j=1;j<=a[i].types;j++)
thing[cnt][mp[a[i].mark[j]]]=a[i].num[j];
}
//Main
int it[6];
for(it[1]=0;it[1]<6;it[1]++) for(it[2]=0;it[2]<6;it[2]++)
for(it[3]=0;it[3]<6;it[3]++) for(it[4]=0;it[4]<6;it[4]++)
for(it[5]=0;it[5]<6;it[5]++) dp[it[1]][it[2]][it[3]][it[4]][it[5]]=1e9;
dp[0][0][0][0][0]=0;
for(int i=1;i<=cnt;i++) for(it[1]=thing[i][1];it[1]<=need[1];it[1]++)
for(it[2]=thing[i][2];it[2]<=need[2];it[2]++) for(it[3]=thing[i][3];it[3]<=need[3];it[3]++)
for(it[4]=thing[i][4];it[4]<=need[4];it[4]++) for(it[5]=thing[i][5];it[5]<=need[5];it[5]++)
Min(dp[it[1]][it[2]][it[3]][it[4]][it[5]],dp[it[1]-thing[i][1]][it[2]-thing[i][2]][it[3]-thing[i][3]][it[4]-thing[i][4]][it[5]-thing[i][5]]+thing[i][0]);
printf("%d\n",dp[need[1]][need[2]][need[3]][need[4]][need[5]]);
return 0;
}

浙公网安备 33010602011771号