例2.11 FatMouse' Trade - 九度教程第21题
题目:
时间限制:1 秒 内存限制:128 兆 特殊判题:否
题目描述:
FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean.
The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and requires F[i] pounds of cat food. FatMouse does not have to trade for all the JavaBeans in the room, instead, he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food. Here a is a real number. Now he is assigning this homework to you: tell him the maximum amount of JavaBeans he can obtain.
输入:
The input consists of multiple test cases. Each test case begins with a line containing two non-negative integers M and N. Then N lines follow, each contains two non-negative integers J[i] and F[i] respectively. The last test case is followed by two -1’s. All integers are not greater than 1000.
输出:
For each test case, print in a single line a real number accurate up to 3 decimal places, which is the maximum amount of JavaBeans that FatMouse can obtain.
样例输入:
5 3
7 2
4 3
5 2
20 3
25 18
24 15
15 10
-1 -1
样例输出:
13.333
31.500
解析:
题目大意如下:有M元钱,N种物品;每种物品有J[i]磅,价值F[i]元。可以使用0到F[i]的任意价格购买相应磅的物品,例如使用 F[i]* a% 元,可以购买J[i]* a% 磅物品。要求输出用M元钱最多能买到多少磅物品。
采用贪心策略,每次都买剩余物品中性价比(即重量价格比)最高的物品,直到该物品被买完或者钱耗尽。
大致思路:
构造结构体,按照性价比从大到小进行sort排序。采用贪心策略,for循环或者while循环依次遍历,每次都买性价比最高的物品。
代码:
#include<stdio.h>
#include<algorithm> //sort函数头文件
using namespace std;
struct goods{ //表示可买物体的结构体
int j; //该物品总重
int f; //该物品总价值
double s; //该物品性价比
bool operator < (const goods &A) const{
//重载小于运算符,确保可用sort函数将数组按照性价比降序排列
return s>A.s;
}
}buf[1000];
int main()
{
int m,n;
while(scanf("%d%d",&m,&n)!=EOF)
{
if(m==-1 && n==-1) //当m==-1且n==-1时跳出循环,程序运行结果
{
break;
}
for(int i=0;i<n;i++)
{
scanf("%d%d",&buf[i].j,&buf[i].f);//输入
buf[i].s=(double)buf[i].j/buf[i].f; //计算性价比
}
sort(buf,buf+n); //使各物品按照性价比降序排列
/* for(int i=0;i<n;i++)
{
printf("%d%d%f\n",buf[i].j,buf[i].f,buf[i].s);
}*/
int idx=0; //当前货物下标
double ans=0; //累加所能得到的总重量
while(m>0 && idx<n) //循环条件为,既有物品剩余(idx<n)还有钱剩余(m>0)时继续循环
{
if(m>buf[idx].f)
{
m-=buf[idx].f;
ans+=buf[idx].j;
} //若能买下全部该物品
else
{
ans+=(double)m*buf[idx].j/buf[idx].f;
m=0;
} //若只能买下部分该物品
idx++; //继续下一个物品
}
printf("%.3f\n",ans); //输出
}
return 0;
}
下面控制贪心策略的关键代码, 可以不用while循环,也可以用for循环控制