题目:http://acm.hdu.edu.cn/showproblem.php?pid=1009
译文:题目描述:
从前有只肥肥的老鼠,他叫FatMouse,他就像人类的恐怖分子跟敌人交易军火一样,
猥琐的他准备了M磅猫食,准备与守卫仓库的大猫们进行交易,仓库里有他最爱吃的食物Javabean。
仓库里有N个房间,第i间房间里有J[i]磅Javabean且需要F[i]磅猫食进行交换,FatMouse不必吧
每个房间里的Javabean全部用于交易,
相反,他可以付给大猫F[i]*a%磅猫食,从而换的J[i]*a%磅的Javabean。
其中,a是一个实数,现在他给你布置一个家庭作业,
请你告诉他他最多能够获得多少磅Javabean。
输入描述:
输入包含多组测试数据,每组测试数据的开头一行是两个非负整数M, N.接下来的N行中,
每行包含两个非负整数J[i]和F[i],最后一组测试数据是两个-1,所有的整数的值不糊超过1000;
输出描述:
对于每组测试数据,在一行上打印出一个3位小数的实数,
这个实数是FatMouse能够交易到的最大数量的Javabean.
Sample Input
5 3
7 2
4 3
5 2
20 3
25 18
24 15
15 10
-1 -1
Sample Output
13.333
31.500
这道题的刚开始,题目看的我晕头转向(PS:本人英语渣)。使尽浑身解数终于明白题意,乍一看题目很简单,结果提交wa,我就纳闷了。最后终于发现问题所在。原来快排qsort 对于 double 型有个 “bug”。( 在对浮点或者double型的一定要用三目运算符因为如果也使用整型那样的想减的话,如果是两个很接近的数则可能返回一个小数(大于-1,小于1),而cmp的返回值是int型,因此会将这个小数返回0,系统认为是相等,失去了本来存在的大小关系。)解决这个问题后总算ac了。
现在我来说说解题思路吧:
1、实际上可以把FatMouse的M猫粮看做钱,那么这个问题就转化为买东西(就和 hdu2090 算菜价那题一样了)。把M磅猫粮看做钱之后,那么 j[i]/f[i] 就变成了单价。现在就成为 用M的猫粮来购买最多的Javabean的问题。
2、现在对 j[i]/f[i] 进行排序。
3、 j[i]/f[i] 相当于单价,要买的最多当然是先买便宜的
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN 1000+10
typedef struct{
double j,f,a;
}Mouse;
Mouse trade[MAXN];
int cmp(const void*a,const void*b){
Mouse *A=(Mouse*)a;
Mouse *B=(Mouse*)b;
if( A->a == B->a )
return B->j>A->j?1:-1;
return B->a>A->a?1:-1;
}
int main()
{
int n,i;
double sum,m;
while(~scanf("%lf%d",&m,&n)){
if(m==-1||n==-1) break;
memset(trade,0,sizeof(trade));
for(i=0;i<n;i++){
scanf("%lf%lf",&trade[i].j,&trade[i].f);
trade[i].a=1.0*trade[i].j/trade[i].f;
}
qsort(trade,n,sizeof(trade[0]),cmp);
sum=0;
for(i=0;i<n;i++){
if(trade[i].f<m){
sum+=trade[i].j;
m-=trade[i].f;
}
else{
sum+=trade[i].j/trade[i].f*m;
break;
}
}
printf("%.3lf\n",sum);
}
return 0;
}