思路:一种商品最多能买5个所以可以用六进制数表示 状态压缩DP 转化成背包问题 一种组合看作一个新的类型的物品
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define inf 0x3f3f3f3f3f
using namespace std;
int id[1005];
int num[10];
int six[]={0,1,6,36,216,1296,7776,46656};//各位置权值
int dp[110000];
int get_six(int*p) //六进制转十进制
{
int res=0;
for(int i=1;i<=5;i++)res+=p[i]*six[i];
return res;
}
struct Node{
int num,state,v;
}node[110000];
int main(){
int n,m;
while(cin>>n){
int sum=0;
int maxstate=0;
for(int i=1;i<=n;i++){
int temp;
cin>>temp;
id[temp]=i;
cin>>node[i].num>>node[i].v;
sum+=node[i].num*node[i].v;
node[i].state=six[i];
maxstate+=six[i]*node[i].num;
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
int x;
cin>>x;
memset(num,0,sizeof(num));//记得归零
for(int j=1;j<=x;j++){
int tempid,tempnum;
cin>>tempid>>tempnum;
num[id[tempid]]=tempnum; //在属于在id的位置上给出数量 最后用get_six转化成六进制数 如 0540 id为1的5个 id为2的5个 即为 5*1+5*6
}
node[i+n].state=get_six(num);
cin>>node[i+n].v;
}
for(int i=0;i<=maxstate;i++)dp[i]=inf;//组合看作一种物品即可用背包算
dp[0]=0;
for(int i=0;i<=maxstate;i++){
for(int j=1;j<=n+m;j++){
dp[i+node[j].state]=min(dp[i+node[j].state],dp[i]+node[j].v);
}
}
sum=min(sum,dp[maxstate]);//要么都用单价 要么组合起来
cout<<sum<<endl;
}
return 0;
}