最近在学习dp,这道题感觉挺不错的,(蟹蟹亲爱哒细心讲解,手动艾特,最喜欢你啦~)
题意:购物车里有b种(0=<b<=5)物品,每种物品告诉物品代号c(1=<c<=999),数量为k(1=<k<=5),单价为p.超市有s种优惠方案,每种优惠方案包含n种物品,分别告诉这n种物品的代号和数量以及打包后的价格。询问刚好把购物车的东西买完,最少的花费。
解题思路:离散+状压dp(完全背包)
物品编号不确定,个人用map离散了
因为物品个数最多为5,所以进行六进制压缩,这个我一开始没有理解啊,然后对应十进制想一下就能懂了
6>>10 36>>100 216>>1000
之后你就能储存单个物品的状态,以及优惠礼包的状态了,接下来就是完全背包的问题
代码已AC
#include<iostream>
#include <cstdio>
#include<stack>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
#include<map>
using namespace std;
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define mem(a,x) memset(a,x,sizeof(a))
#define LL long long
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
const int inf=0x3f3f3f3f;
int dp[200000];
int state[500];
int w[]={1,6,36,216,1296,7776,46656};
int b,c,k,ask,n,s,p,cnt;
int value[500];
map<int,int>mp;
struct node
{
int c,k,p;
}t[7];
int main()
{
scanf("%d",&b);
fill(dp,dp+50000,inf);
dp[0]=0;cnt=0;
F(i,0,b-1)
{
scanf("%d%d%d",&c,&k,&p);
mp[c]=i;//离散
// cout<<mp[t[i].c]<<endl;
value[cnt]=p;
state[cnt++]=w[i];//单个物品状态
ask+=w[i]*k;
}
scanf("%d",&n);
F(i,0,n-1)
{
scanf("%d",&s);
int u=0;
while(s--)
{
scanf("%d%d",&c,&k);
u+=w[mp[c]]*k;
}
scanf("%d",&p);
value[cnt]=p;
state[cnt++]=u;//每种优惠状态
}
F(i,0,b+n-1)//完全背包
{
F(j,state[i],ask)
{
dp[j]=min(dp[j],dp[j-state[i]]+value[i]);
// cout<<j<<" "<<dp[j]<<" "<<endl;
}
// cout<<endl;
}
printf("%d",dp[ask]);
return 0;
}