0-1背包(商品组合)
题意:
有n种(最多5种)商品,每种商品三个属性,自己的名字(数字),总量,价钱。现在商家正在进行打折活动,几种商品组合的价钱会比原价低。有s种组合每种组合第一个数字是有n种商品组合成一起,然后n对数字
代表商品的名字和数量,最后一个数字表示这个组合的总价钱。
最后输出,要买所有商品最少花多少钱?
思路:
每种商品都要买,这是0-1背包问题,但是问题是怎么把每种组合算在其中。
解决的办法是把每一种组合当做一个商品,我们记录每一种组合中的商品个数,我们如果选择了这一个商品,就会减去相应物品的个数与之比较。
dp[a][b][c][d][e]表示五种商品分别买的个数花费的最少钱数。
- 注意一个点:每一个商品的名字很大,这道题可以用数组开出来,其实即使更大我们可以用map标记,进行离散化。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 100;
struct goods
{
int code,cnt,price;
}g[6];
const int INF = 0x3f3f3f3f;
int n,s;
int dp[6][6][6][6][6];
int p[maxn][maxn*10+5]; //表示组合i,花费物品j的个数
int reduced[maxn];
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i = 1;i <= n; i++) {
scanf("%d%d%d",&g[i].code,&g[i].cnt,&g[i].price);
}
scanf("%d",&s);
for(int i = 1;i <= s; i++) {
int goods_cnt;
scanf("%d",&goods_cnt);
for(int j = 1;j <= goods_cnt; j++) {
int tcode,tcnt;
scanf("%d%d",&tcode,&tcnt);
p[i][tcode] = tcnt;
}
scanf("%d",&reduced[i]);
}
for(int a = 0;a <= g[1].cnt; a++) {
for(int b = 0;b <= g[2].cnt; b++) {
for(int c = 0;c <= g[3].cnt; c++) {
for(int d = 0;d <= g[4].cnt; d++) {
for(int e = 0;e <= g[5].cnt; e++) {
dp[a][b][c][d][e] =
a*g[1].price + b*g[2].price
+ c*g[3].price + d*g[4].price +
e*g[5].price;
for(int i = 1;i <= s; i++) {
int a1 = a - p[i][g[1].code];
int b1 = b - p[i][g[2].code];
int c1 = c - p[i][g[3].code];
int d1 = d - p[i][g[4].code];
int e1 = e - p[i][g[5].code];
if(a1 < 0 || b1 < 0 || c1 < 0 || d1 < 0 || e1 < 0) continue;
int temp = dp[a1][b1][c1][d1][e1] + reduced[i];
dp[a][b][c][d][e] = min(dp[a][b][c][d][e],temp);
}
}
}
}
}
}
printf("%d\n",dp[g[1].cnt][g[2].cnt][g[3].cnt][g[4].cnt][g[5].cnt]);
return 0;
}