题目大意:
在商店中,每一种商品都有一个价格。
商店 把一个或多个商品组合起来降价销售,形成优惠方案,
编写一个程序,计算顾客购买一定商品的花费,利用优惠使花费最少。
** 尽管有时候添加其他商品可以获得更少的花费,但是你不能这么做。**
解析题目:
这道题就是五维暴力,但 易错点很多,恶心,是道毒瘤题
不愧是IOI的真题
暴力,数据较小,且最多五种商品
注意!尽管有时候添加其他商品可以获得更少的花费,但是你不能这么做
比如你要买三个苹果,两根香蕉,花了11z
方案是三个苹果,三根香蕉花了10z
那也不行,因为浪费了一根香蕉
(宣传不浪费的IOI)
状态:\(f_{i,j,k,l,q}\)表示 买 i 的第一种商品 ,买 j 的第二种商品 ,买 k 的第三种商品 ,买 l 的第四种商品 ,买 q 的第五种商品 的最小花费
如果不足五种怎么办?其实不慌,比如如果有三种 ,l,q将一直等于0,不影响使用
我们还需要一个二维数组p,\(p_{i,j}\)表示第i种优惠里商品j所需的数量。
模拟即可
详细讲解:
先来介绍一下没什么用快读吧
在 C++ 中,读入字符要比读入数字快
因此,我们可以读入字符,将其转为数字
在一百万次输入后,快读将比scanf快1秒
其实这道题不用快读,是我打时不知道怎么想的
inline int read()
{
int ans = 0;
char c = getchar();
while ((c < '0' || c > '9') )//筛掉空格、换行等
{
c = getchar();
}
ans = c - '0';//正式开始读入
c = getchar();
while (c >= '0' && c <= '9')
{
ans = (ans << 3) + (ans << 1);//位运算比正常计算快,这个位运算等价于ans*=10;
ans += c - '0';
c = getchar();
}
return ans;
}//总之就生活小妙招了属于是
见样例,虽然 只有5种,
但编号不一定是1~5,我们需要在输入时自行编号,一个h数组即可,map会WA
由于一个编号会出现多次,要先判断h[x]是否为0,是0才编号
for(int i=1;i<=s;i++)//s是方案数
{
n=read();
for(int j=1;j<=n;j++)
{
b=read();
if(h[b]==0)h[b]=++tmp;//编号
p[i][h[b]]=read();
}
money[i]=read();//money是 优惠方案的价钱 的意思
}
在下面也是一样的
for(int i=1;i<=b;i++)//b是我们要买的种类数
{
int x=read();
if(h[x]==0)h[x]=++tmp;
//同上,是0才编号
need[h[x]]=read(); //need表示我们一共需要多少个
old[h[x]]=read();//old 表示原价
}
接下来是初始化
默认是全用原价
for(int i=0;i<=need[1];i++)
{
for(int j=0;j<=need[2];j++)
{
for(int k=0;k<=need[3];k++)
{
for(int l=0;l<=need[4];l++)
{
for(int q=0;q<=need[5];q++)//五重暴力初始化,求出所有的原价
//注意也要考虑0,不买也不是不行
{
f[i][j][k][l][q]=old[1]*i+old[2]*j+old[3]*k+old[4]*l+old[5]*q;
}
}
}
}
}
谁写的顺口溜?
接下来是可怕的六重循环解析
for(int m=1;m<=s;m++)
{
代码:我裂开了
m表示当前考虑的方案
然后继续看
我们要枚举i,j,k,l,q
对于范围,不足 p[m]就不能实现方案了,超过need就浪费了
所以是p[m]~need
for(int i=p[m][1];i<=need[1];i++)
{
for(int j=p[m][2];j<=need[2];j++)
{
for(int k=p[m][3];k<=need[3];k++)
{
for(int l=p[m][4];l<=need[4];l++)
{
for(int q=p[m][5];q<=need[5];q++)//从i到q都一样,只是表示的 要买的东西 不同
解析一下转移方程
当求 \(f_{i,j,k,l,q}\)时,
应该将其分解成子问题
显然,我们只用考虑 卖完还需要的东西构成的子问题 加上 方案价格 再比较大小 即可
{
if(f[i][j][k][l][q]>=f[i-p[m][1]][j-p[m][2]][k-p[m][3]][l-p[m][4]][q-p[m][5]]+money[m])
{
f[i][j][k][l][q]=f[i-p[m][1]][j-p[m][2]][k-p[m][3]][l-p[m][4]][q-p[m][5]]+money[m];
}
}
别忘了括号
}
}
}
}
}