一:杭电原题摘录
http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=1§ionid=3&problemid=1
二.题目分析
题目大意就是一只肥鼠想要用自己的猫粮尽可能多的换取猫手里的咖啡豆.输入会告诉你肥鼠手里的猫粮数5,和兑换规则:
咖啡豆X | 猫粮Y |
7 | 2 |
4 | 3 |
5 | 2 |
要想换得最多的咖啡豆,那我们要从最佳兑换比换起,显然是7/2,然后是5/2,最后是4/3.当然我们需要考虑肥鼠手里的猫粮数,如果不够,那么只能按比率兑换.比如上表这个但兑换到最后一个4/3时,肥鼠手里只剩下1个猫粮时,他只能换取4/3=1.333咖啡豆.
所以我们要先将X/Y按从大到小排列.然后依次取,超出的只取未超出的部分就ok了.
三.我的收获
1.输出控制:像这种要求有输出精度控制的最好用printf,但一定记得加\n;
当然也可以用<iomanip>. cout<<fixed<<setprecision(3)<<ans<<endl;
2.结构体数组的使用,sort(a,a+N,cmp)库函数的使用极其方便.
3.贪心算法(部分背包);还有0,1背包问题跟这个差不多,不同的是0,1背包问题要么全取,要么全不取.
四.AC代码
#include <cstdio> //贪心算法
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int N,M;
struct node{
int x,y;
double s;
}a[1000];
double cmp(node aa,node bb){
return aa.s>bb.s;
}
int main(){
double sum,ans,w;
int l,k;
while(~scanf("%d %d",&M,&N)){
if(M==-1&&N==-1) break;
for(int i=0;i<N;i++){
scanf("%d %d",&a[i].x,&a[i].y);
a[i].s=(1.0*a[i].x/a[i].y);
}
sort(a,a+N,cmp);
sum=0.0,ans=0.0;
for(int i=0;i<N;i++){
if(sum<M){
if(sum+a[i].y<=M){
ans+=a[i].x;
sum+=a[i].y;
}
else{
ans+=a[i].s*(M-sum);
sum=M;
}
}
else {
break;
}
}
printf("%.3lf\n",ans);
}
return 0;
}