質問の意味: b種類の商品を含む注文、注文の各アイテムの初期価格と購入する必要のある数量を指定し、次にs種類のパッケージを指定すると、これらの組み合わせはより安い価格になります。それらを一致させて合計価格を最小化します。
解決策:各商品に対応する次元を設定します。各商品の数は5を超えないため、10進法と同様に16進法に対応します。
例:1積x1、2積x2、3積x3 ...次に、x1 * 6の0乗+ x2 * 6の累乗+ x3 * 6の2乗+に圧縮されます。。。+ xn * 6のn-1乗。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
void io() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); }
const int inf=0x3f3f3f3f;
int dp[500005],h[1005];
int six[]={1,6,36,216,1296,7776,46656};
struct node{
int has,num,val;
}a[210];
int main() {
io();
int b;
while(cin>>b){
int ans=0,NUM=0; //ans:单独购买所需钱数 NUM:购买完所有商品对应的状态
memset(h,-1,sizeof h); //商品号对应的六进制状态
for(int i=0;i<b;i++) {
int x;
cin>>x>>a[i].num>>a[i].val;
h[x]=six[i];
a[i].has=six[i];
ans+=a[i].num*a[i].val;
NUM+=six[i]*a[i].num;
a[i].num=six[i]; //将其数量转换成其对应的状态
}
int n,x; cin>>n;
for(int i=0;i<n;i++) {
cin>>x;
int c,k;
while(x--){
cin>>c>>k;
if(h[c]==-1) continue;
a[i+b].num+=h[c]*k; //将套餐变为对应的六进制
}
cin>>a[i+b].val;
}
memset(dp,inf,sizeof(dp));
dp[0]=0; //完全背包
for(int i=0;i<b+n;i++){
for(int j=a[i].num;j<=NUM;j++)
dp[j]=min(dp[j],dp[j-a[i].num]+a[i].val);
}
cout<<min(ans,dp[NUM])<<endl;
}
return 0;
}
参照リンク:https://blog.csdn.net/stay_accept/article/details/51164607