题目描述
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入描述
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出描述
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
输入例子
3 20
18 15 10
75 72 45
输出例子
94.50
我的代码
#include<stdio.h>
#define N 1000
typedef struct mylist{ //创建结构体
int a; //库存
int b; //总利润
double c; //利润率
}LIST;
int main(){
LIST p[N],t;
int i,j,n,d;
double w;
scanf("%d %d",&n,&d);
for(i=0;i<n;i++){
scanf("%d",&p[i].a); //每一种的库存
}
for(i=0;i<n;i++){
scanf("%d",&p[i].b); //每一种的总售价
}
for(i=0;i<n;i++){
p[i].c=(double)p[i].b/(double)p[i].a; //每一种的利润率
}
for(i=0;i<n-1;i++){ //冒泡排序
for(j=i+1;j<n;j++){
if(p[i].c<p[j].c){
t=p[i];
p[i]=p[j];
p[j]=t;
}
}
}
for(i=0;i<n;i++){
if(d>=p[i].a){ //如果库存大于利润率最大的月饼的库存
w=w+p[i].b; //利润率最大的月饼全卖光
d=d-p[i].a; //库存=原库存-利润率最大的月饼的库存
}
else if(d<p[i].a){ //如果库存小于利润率最大的月饼库存
w=w+d*p[i].c; //只卖库存的数量
break; //跳出循环
}
}
printf("%.2f",w); //输出2位小数
return 0;
}
我的分析
这道题一开始确实是把我难倒了,我一开始的思路是类似于中学学的方程那样将总利润w用未知数来表示出来,然后依靠计算的使用穷举法进行计算,但是问题出在我并不知道系统将要给出几个类别的的月饼,所以不知道要循环几次,所以这种方法不行。然后转换为另一种思路,先计算每一种月饼的利润率(月饼的利润/月饼的库存量),然后按照利润率从大到小的顺序来排列,之后是如果库存小于市场需求量,则先将利润率高的月饼的库存全部卖光,然后计算剩余的库存,再接着卖第二种月饼,以此类推,直到满足市场需求量。
其实这道题在实现我上面的算法时没有花多少时间,但是在选择定义的数据类型以及输出的两位数上花掉了我一些时间。基础没有打好,有点不应该。
收获
这道题让我重新审视了不同数据类型之间的运算,发现如果定义时的类型不同,则两个变量进行计算后的结果也会差别很大。所以在这里总结一下:
1.如果两个数定义时都是int,则在输出时不论怎么怎么改变%或者是强制转换,它的值永远不会改变(有些只是在小数点后面加一些无关紧要的0)。
2.如果在某些题目中需要精确到小数点后面的小数,则一般定义时都是定义为double类型(double类型也可以接受输入类型为整型)但是他们在输出时必须使用%f或者是它的衍生,绝对不能是%d,否则输出时会是错误的。
3.如果记不住,则就记住这一句话,凡是涉及到精确运算的把运算符前后的数字类型都定义为int,而将它们计算之后的值定义为double,然后在计算是运用强制转换类型将运算数转换为double型,之后不论什么运算都不会出错
网友评论