在商店中,每一种商品都有一个价格(用整数表示)。例如,一朵花的价格是 2 zorkmids (z),而一个花瓶的价格是 5z 。为了吸引更多的顾客,商店举行了促销活动。
促销活动把一个或多个商品组合起来降价销售,例如:
三朵花的价格是 5z 而不是 6z, 两个花瓶和一朵花的价格是 10z 而不是 12z。 编写一个程序,计算顾客购买一定商品的花费,尽量利用优惠使花费最少。尽管有时候添加其他商品可以获得更少的花费,但是你不能这么做。
对于上面的商品信息,购买三朵花和两个花瓶的最少花费是:以优惠价购买两个花瓶和一朵花(10z),以原价购买两朵花(4z)。
格式
PROGRAM NAME: shopping
INPUT FORMAT:(file shopping.in)
输入文件包括一些商店提供的优惠信息,接着是购物清单。
第一行 优惠商品的种类数(0 <= s <= 99)。
第二行..第s+1 行 每一行都用几个整数来表示一种优惠方式。第一个整数 n (1 <= n <= 5),表示这种优惠方式由 n 种商品组成。后面 n 对整数 c 和 k 表示 k (1 <= k <= 5)个编号为 c (1 <= c <= 999)的商品共同构成这种优惠,最后的整数 p 表示这种优惠的优惠价(1 <= p <= 9999)。优惠价总是比原价低。
第 s+2 行 这一行有一个整数 b (0 <= b <= 5),表示需要购买 b 种不同的商品。
第 s+3 行..第 s+b+2 行 这 b 行中的每一行包括三个整数:c ,k ,和 p 。 C 表示唯一的商品编号(1 <= c <= 999),k 表示需要购买的 c 商品的数量(1 <= k <= 5)。p 表示 c 商品的原价(1 <= p <= 999)。最多购买 5*5=25 个商品。
OUTPUT FORMAT:(file shopping.out)
只有一行,输出一个整数:购买这些物品的最低价格。
SAMPLE INPUT
2
1 7 3 5
2 7 1 8 2 10
2
7 3 2
8 2 5
SAMPLE OUTPUT
14
分析:
0 <= b <= 5,1 <= k <= 5,可用5*5*5*5*5的DP 每种买0~5个,可以用6进制表示,然后5维DP~OK!
状态设置:F[a1][a2][a3][a4][a5]为买a1件物品1,a2件物品2,a3件物品3,a4件物品4,a5件物品5时,所需的最少价格
边界条件:F[0][0][0][0][0]=0;
状态转移方程:
F[a1][a2][a3][a4][a5]=min{F[ a1-P[i][1] ][ a2-P[i][2] ][ a3-P[i][3] ][ a4-P[i][4] ][ a5-P[i][5] ]+P[i][0])}
其中i=1..s+b; 且 ak-p[i][k]>=0
【参考程序】:
/*
ID: XIONGNA1
PROG: shopping
LANG: C++
*/
#include<iostream>
#include<cstring>
using namespace std;
int v[6],w[6],c[6],lz[100],hz[100][6];
int mz[100][6],z[100][6],ys[100];
int f[6][6][6][6][6];
bool ok[100];
int n,m;
int Find(int now)
{
for (int i=1;i<=m;i++)
if (v[i]==now) return i;
return 0;
}
int main()
{
freopen("shopping.in","r",stdin);
freopen("shopping.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&lz[i]);
for (int j=1;j<=lz[i];j++)
scanf("%d%d",&hz[i][j],&mz[i][j]);
scanf("%d",&ys[i]);
}
scanf("%d",&m);
for (int i=1;i<=m;i++)
scanf("%d%d%d",&v[i],&w[i],&c[i]);
memset(ok,true,sizeof(ok));
int x,y,pos;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=lz[i];j++)
{
x=hz[i][j]; y=mz[i][j];
pos=Find(x);
if (pos==0) ok[pos]=false;
if (ok[pos]) z[i][pos]=y;
}
}
for (int i1=0;i1<=w[1];i1++)
for (int i2=0;i2<=w[2];i2++)
for (int i3=0;i3<=w[3];i3++)
for (int i4=0;i4<=w[4];i4++)
for (int i5=0;i5<=w[5];i5++)
f[i1][i2][i3][i4][i5]=i1*c[1]+i2*c[2]+i3*c[3]+i4*c[4]+i5*c[5];
for (int i=1;i<=n;i++)
if (ok[i])
for (int i1=z[i][1];i1<=w[1];i1++)
for (int i2=z[i][2];i2<=w[2];i2++)
for (int i3=z[i][3];i3<=w[3];i3++)
for (int i4=z[i][4];i4<=w[4];i4++)
for (int i5=z[i][5];i5<=w[5];i5++)
if (f[i1][i2][i3][i4][i5]>f[i1-z[i][1]][i2-z[i][2]][i3-z[i][3]][i4-z[i][4]][i5-z[i][5]]+ys[i])
f[i1][i2][i3][i4][i5]=f[i1-z[i][1]][i2-z[i][2]][i3-z[i][3]][i4-z[i][4]][i5-z[i][5]]+ys[i];
printf("%d\n",f[w[1]][w[2]][w[3]][w[4]][w[5]]);
return 0;
}