链接:点击打开链接
题意:给定一个含有n种商品的订单,给出订单内每个物品的初始价格和需要购买的数量,再给出m种套餐,这些组合会得到便宜的价格,最后怎样搭配使得总价格最少。
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int dp[500005],HASH[1005];
int SIX[10]={1,6,36,216,1296,7776,46656,279936};
struct node{
int has,num,val;
}s[205];
int main(){ //因为最多有五种物品,因此
int b,k,m,x,y,i,j,ans,tmp,NUM; //将每种物品和套餐用六进制
while(scanf("%d",&b)!=EOF){ //进行状态压缩
ans=NUM=0;
memset(HASH,-1,sizeof(HASH));
for(i=0;i<b;i++){
scanf("%d%d%d",&tmp,&s[i].num,&s[i].val);
s[i].has=SIX[i];
HASH[tmp]=SIX[i];
ans+=s[i].num*s[i].val;
NUM+=SIX[i]*s[i].num; //将六进制总数作为背包容量
s[i].num=SIX[i]; //将每个物品的重量变为六进制
} //所表示的数
scanf("%d",&m);
for(i=0;i<m;i++){
scanf("%d",&k);
while(k--){
scanf("%d%d",&x,&y);
if(HASH[x]==-1)
continue;
s[i+b].num+=HASH[x]*y; //将套餐变为六进制数
}
scanf("%d",&s[i+b].val);
}
memset(dp,INF,sizeof(dp));
dp[0]=0;
for(i=0;i<b+m;i++)
for(j=s[i].num;j<=NUM;j++) //直接转换成完全背包
dp[j]=min(dp[j],dp[j-s[i].num]+s[i].val);
printf("%d\n",min(ans,dp[NUM]));
}
return 0;
}