【hdoj_1009】FatMouse's Trade

来源:互联网 发布:淘宝七天退货时间计算 编辑:程序博客网 时间:2024/05/17 03:21
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1009<

本题用到贪心策略和结构体排序。

问题简化:现有资本M,N个房间,第i个房间对应着价格为F[i]和收益J[i],需要将M全部花光去投资每个房间,使得收益最大,从每个房间中获取的效益与投入成正比,求最大获益。

贪心策略:由于成正比,收益与投资成正比,所以可以考虑“性价比”这个概念,把每个房间当作一个商品,则该商品的性价比=收益/价格,然后按照性价比从大到小排序,然后将资本M按顺序投资到每个房间,直到M为0或全部投资完。

将每个房间作为一个结构体变量,结构体含有数据成员:收益J和价格F。如何对结构体进行排序?只需要定义两个结构体是如何比较大小的即可,即需要说明:对结构体而言,>和<等不等符号分别是什么意思,因而要用到运算符重载。此处是按照 J/F的大小排序的,所以F不能为0,事实上,题目没有限制F是否为0,所以需要考虑F=0的情况。下面来看如何定义两个房间的大小关系的,用于运算符 > 的重载。

房间R1和R2:

R1.F=0且R2.F=0,这意味着,二者价格均为0,所以定义谁的收益大,谁就大。

R1.F!=0且R2.F=0,这意味着R2价格为0,所以定义R2大。(有可能R1和R2的收益均为0,那么二者就相等了,但实际投资过程中,当然不会投资R1和R2,所以定义R2比R1大还是相等不重要)

R1.F=0且R2.F!=0,这意味着R1价格为0,所以定义R1大。

R1.F!=0且R2.F!=0,这种情况,直接按照J/F定义R1和R2的大小即可。

用Dev-C++编写的C++代码:(提交之后AC)


#include <iostream>#include <iomanip>using namespace std;struct Room  //定义结构体 {double J,F;//两个数据成员 Room(double j=0.0,double f=0.0)  //构造函数,最好带有默认形参 {J = j;F = f;}void setRoom(double j,double f)  //用于给结构体变量的两个数据成员赋值的函数 {J = j;F = f;}bool operator > (Room room)  //运算符 > 的重载 {if (F==0 && room.F==0)    return J > room.J;         //都为0else if(F==0 && room.F!=0)    return 1;else if(F!=0 && room.F==0)    return 0;else    return (J/F) > (room.J/room.F);    //都不为0   }};void BinSort(Room *R,int N)  //折半插入排序 {for(int i=1;i<N;i++){int low=0,high=i-1,mid;while(low<=high){mid = (low+high) / 2;if(R[i]>R[mid])  //此处用到了结构体之间 > 的关系,如果没有运算符 > 的重载会报错,这里用 > 而不用 < 使得排序是按照从大到小排序的 high = mid - 1;else low = mid + 1; }Room temp = R[i];  //这里用到结构体自带的赋值运算符,不用重载 for(int j=i;j>low;j--)R[j] = R[j-1];R[low] = temp;}}int main(){int M,N,k=0,kk=0;double J,F;double result[1000];  //存储最终结果 while(1){cin >> M >> N;if(M==-1 && N ==-1)break;else{double tot = 0.0;       //用于记录结果,每次清零 Room *R = new Room[N];  //针对每组数据,开N个房间 for(int i=0;i<N;i++)    //输入每个房间的两个参数,收益J和价格F {cin >> J >> F;R[i].setRoom(J,F);}BinSort(R,N);  //排序 for(int j=0;j<N && M>0 ;j++)   //逐个投资,直到投资完所有房间或者资本花光 {// 遇到第i个房间的两种可能情况if(M>=R[j].F)   //一:资本足够 {M -= R[j].F;  // 花掉了所需价格的资本 tot += R[j].J;  // 获得的对应的全部收益 }else  //二:资本不够 {M = 0; //资本花光tot += M/R[j].F*R[j].J;  //按正比收益一部分 }}result[k++] = tot; // 记录结果 }}for(int i=0;i<k;i++)cout << setprecision(3) << fixed << result[i] << endl; return 0;}

说明:

1.如对折半插入排序算法有疑问,可以参考:

http://blog.csdn.net/ten_sory/article/details/51731823

2.在C++中将结果保留三位小数的方法需要加载头文件#include<iomanip>,代码是:

cout << setprecision(3) << fixed << 3.1415926 << endl;


如有纰漏,欢迎指正!

1 0
原创粉丝点击