题目: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; //都为0
else 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;

如有纰漏,欢迎指正!

【hdoj_1009】FatMouse's Trade的更多相关文章

  1. 【HDU】3401:Trade【单调队列优化DP】

    Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  2. 【单调队列优化dp】HDU 3401 Trade

    http://acm.hdu.edu.cn/showproblem.php?pid=3401 [题意] 知道之后n天的股票买卖价格(api,bpi),以及每天股票买卖数量上限(asi,bsi),问他最 ...

  3. WEB网络问题的排查【转】

    Browser/Server结构主要是利用了不断成熟的Web浏览器技术:结合浏览器的多种脚本语言和ActiveX技术,用通用浏览器实现原来需要复杂专用软件才能实现的强大功能,同时节约了开发成本.B/S ...

  4. plantuml使用教程【转】

    plantuml使用教程[转]   Table of Contents 前言 什么是PlantUML 在Emacs里配置PlantUML(参考:Run it from Emacs) 其他软件里的Pla ...

  5. 【03】Html书写规范

    [03]   Html书写规范   1.推荐使用html5的文档声明 <!DOCTYPE HTML> 2.必须申明文档的编码charset,且与文件本身编码保持一致,推荐使用UTF-8编码 ...

  6. 【Java】阿里巴巴开发规范手册

    Java 开发手册 一. 编程规约 (一) 命名风格 [强制]代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例: _name, $name, __name [强制]代码中 ...

  7. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  8. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  9. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

随机推荐

  1. 基于C#的PISDK研究(理论)

    本篇文章主要对PISDK体系结构以及重点类进行阐述. 当我们决定使用PISDK时,可能会使用到下面的类库: 在上表中,PISDK.dll为核心类,大部分主要功能都在该类中.PISDKCommon.dl ...

  2. java线程(1)——三种创建线程的方式

    前言 线程,英文Thread.在java中,创建线程的方式有三种: 1.Thread 2.Runnable 3.Callable 在详细介绍下这几种方式之前,我们先来看下Thread类和Runnabl ...

  3. Python执行Linux系统命令的4种方法

    http://www.jb51.net/article/56490.htm (1) os.system 仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息 复制代码代码如下: system( ...

  4. 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并

    题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...

  5. [洛谷P2147][SDOI2008]洞穴勘测

    题目大意:有$n$个洞穴,$m$条指令,指令有三种 $Connect\;u\;v$:在$u,v$之间连一条边 $Destroy\;u\;v$:切断$u,v$之间的边 $Query\;u\;v$:询问$ ...

  6. Codeforces Round #524 (Div. 2) A. Petya and Origami

    A. Petya and Origami 题目链接:https://codeforc.es/contest/1080/problem/A 题意: 给出n,k,k表示每个礼品里面sheet的数量(礼品种 ...

  7. fresco的使用教程

    1.加载依赖 api 'org.xutils:xutils:3.5.0' 2.创建一个myapplication public class MyApplication extends Applicat ...

  8. C. Annoying Present SB题

    C. Annoying Present time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  9. centos关闭ipv6

    1.使用lsmod查看ipv6的模块是否被加载. lsmod | grep ipv6 [root@dmhadoop011 ~]# lsmod | grep ipv6 ipv6              ...

  10. Java中一些知识的归纳总结

    1.包装类型与基本数据类型的区别. Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这使得Java在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据 ...