其他分享
首页 > 其他分享> > E.干饭人

E.干饭人

作者:互联网

问题 E: 干饭人

题目描述

当你做完这一道题的时候,期末考试就结束了。
考完了最后一门,你看着卡里还剩的一点钱陷入了沉思:反正今天就放假啦,把饭卡吃完吧!
终于等到了饭点,干饭人干饭时间,第一个冲向食堂;干饭人干饭魂,干饭人吃饭得用盆!

已知食堂里有n份菜,每份菜会给你带来饱腹感为A1、A2……An,
他们的价格是C1、C2……Cn,由于是最后一天,每个菜只有一份了;食堂阿姨手也不抖了,特地允许如果你钱不够打一个菜,可以用刷一定比例的钱买同比例的菜。即如果一个菜4元一份,饱腹感为2,你可以花2元买半份,获得饱腹感+1.

已知你饭卡里的钱数M,求这一顿能够给你带来的最大饱腹感。

输入
多组数据,每组数据的第一行为两个整数M和n ,用空格隔开, -1 -1 为输入结束标记。接下来n行,每行两个整数 表示食堂里n个菜的饱腹感Ai和价格Ci。(所有数据均小于等于1000)
输出
一个保留3位有效数字的数,表示最大饱腹值

样例输入
4 2
4 7
1 3
5 5
4 8
3 8
1 2
2 5
2 4
-1 -1

样例输出
2.286
2.500

这道题目可能一开始你会摸不着头脑,老样子,一开始我依旧带大家来分析样例输入后,样例输出是怎么得到的。

第一组样例输入
在这里插入图片描述
第二组样例输入
在这里插入图片描述
分析:算出每个菜的单位饱腹感,然后进行排序,最后饭卡里的钱数乘以最大的单位饱腹感即可得到理想的输出。

看上面两个样例是像上面的分析所述,这样计算得到理想输出的。但是仔细想想,这到底对嘛?
其实是有缺陷的,上面两个样例之所以能得到这样的结果是因为最大单位饱腹感所对应的那一种菜的价格都大于你饭卡里的钱数。

第一组样例中,最大单位饱腹感所对应的是第1个菜,该菜的价格为7元,大于你饭卡上的钱数4元;同理,第二组样例中,最大单位饱腹感所对应的是第1个菜(这边默认如果两个菜单位饱腹感相等,则按原来菜的先后顺序进行排序),该菜的价格是8,大于你饭卡上的钱数5。

同时我们也注意到题干中说明今天是最后一天,食堂里面的饭菜都只有一份,所以当你饭卡里面的钱数是大于最大单位饱腹感所对应的那一份菜的价格的时候,就不能简单的用饭卡里面的钱数*最大的单位饱腹感来求得最大饱腹感了,因为菜只有一份。

这时,你应该去单位饱腹感经降序排序后的第2个菜那边按比例去点。

老样子先上代码,然后再慢慢分析!

#include <stdio.h>
#include <stdlib.h>//qsort函数所在的头文件

#define MAX 1001//所有数据均小于等于1000
 
 /*定义一个结构体类型,里面有3个成员。
  第一个成员satiety代表该菜的饱腹感,数据类型为整型;
  第二个成员price代表该菜的价格,数据类型为整型;
  第三个成员average代表该菜的单位饱腹感,数据类型是浮点型,
  为了安全起见,不妨定义为double类型。*/
typedef struct{
	int satiety;
	int price;
	double average;
}Lunch,*luc; 
/*typedef定义新的数据类型,给该结构体类型取了一个别名,
  叫做Lunch,即该结构体类型即Lunch类型;同时定义了一个
  指向该结构体的指针,名为luc。*/

//qsort()降序排序函数,其名为cmp,对结构体中的关键字average进行排序。
int cmp(const void *a,const void *b)
{
	luc pa=(luc)a;
	luc pb=(luc)b;
	double num1=pa->average;
	double num2=pb->average;
	double t=num1-num2;
	if(t<0)
	 return 1;
	 /*qsort()降序排序函数cmp返回值类型一定是整型,
	 因此指针a指向的关键字average<指针b指向的关键字average时,应将前者排在后者的后面,
	 所以返回1。*/
	else
	 return -1;//同理.....
}
//对此有疑惑的兄弟可以看代码下方的qsort()降序排序的原理图


int main(int argc, char *argv[]) {
	int M,n,i,x,y;
	
	scanf("%d%d",&M,&n);//输入饭卡里的钱数M和菜的个数n。
	while((M!=-1)&&(n!=-1))//循环终止条件。
{
	Lunch s[n];//定义一个Lunch类型的数组,该数组名为s,该数组大小为n,即菜的个数。
	for(i=0;i<n;i++)
	 {
	 	scanf("%d%d",&s[i].satiety,&s[i].price);//输入菜的饱腹感和价格。
	 	s[i].average=(double)s[i].satiety/s[i].price;
	 	 //计算出该菜的单位饱腹感,这边进行强制类型转换,将其转为double类型。
	 }
	 
	qsort(s,n,sizeof(s[0]),cmp);//qsort()函数对s数组进行排序。
	double max=0;//定义double类型的变量max,代表最大饱腹感,初始化为0。
	
	/*如果饭卡上的钱数大于最大的单位饱腹感的菜所对应的价格,则取完最大单位饱腹感对应的菜以后
	再取第二大的......详细见代码上方分析,这边就不再赘述了。*/
	for(i=0;i<n;i++)
  {
	if(M>s[i].price)
	{
		max+=s[i].satiety;
		M-=s[i].price;
	}
	else
	{
		max+=M*s[i].average;
		break;
	}
  }

    //max=M*s[0].average;//错误示范。
    printf("%.3lf\n",max);//输出最大饱腹感,保留三位有效数字
	scanf("%d%d",&M,&n);//循环输入。
}
	return 0;
}

附qsort()函数原理图:
在这里插入图片描述
总体而言,分析下来该题的难度算是中等,主要考察了qsort()函数对结构体中的某个成员进行排序,其次便是一些小处理,懂得灵活变通是本题能够解决的关键。
如果对qsort()函数对结构体的某个关键字进行排序不清楚的小伙伴可以点击下方的链接。
传送门:https://www.bilibili.com/video/BV1Nx411D7sU(个人认为全网讲解qsort()函数最好的视频)
好了本期分享就先到这边,感谢大家的围观!

标签:钱数,饭卡,qsort,饱腹,double,样例,干饭
来源: https://blog.csdn.net/qq_46139801/article/details/113478311