D – FatMouse‘ Trade HUOJ

题目

FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean.
胖老鼠准备了M磅的猫粮,准备与守卫他最喜欢的食物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.
仓库有N个房间。第 i 个房间包含 J[i] 磅的 JavaBeans,需要 F[i] 磅的猫粮。FatMouse 不必交易房间里的所有 JavaBeans,相反,如果他支付 F[i]* a% 磅的猫粮,他可能会得到 J[i]* a% 磅的 JavaBeans。这里 a 是一个实数。现在他正在给你布置这个作业:告诉他他能获得的最大 JavaBeans 数量。

Input

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.
输入由多个测试用例组成。每个测试用例都以包含两个非负整数 M 和 N 的行开头。然后是 N 行,每行分别包含两个非负整数 J[i] 和 F[i]。最后一个测试用例后面跟着两个 -1。所有整数都不大于 1000。

Output

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.
对于每个测试用例,在一行中打印一个精确到小数点后 3 位的实数,这是 FatMouse 可以获得的最大 JavaBean 数量。

Sample

Inputcopy Outputcopy
5 3
7 2
4 3
5 2
20 3
25 18
24 15
15 10
-1 -1
13.333
31.500

思路

为了尽可能换取多的JavaBean,我们要尽可能多的去兑换性价比较高的JavaBean,因此可以使用我们所学过的multimap容器,这样可以为我们防止有相同性价比的商店,同时可以根据性价比的倒数正序排列,也就是按性价比越高越在前,猫粮够的话就全换完,不够了就尽可能换,同时停止,具体代码如以下实现。

代码实现

#include <iostream>
#include <map>
using namespace std;
int main() {
    std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);//关闭同步流
	double m, n;
	double x, y, sum;
	while (cin >> m >> n, m != -1) {
		sum = 0;
		multimap<double, double>mp;//采用multimap用于排序和防止同性价比情况
		while (n--) {
			cin >> x >> y; //y是换的,key越小,越优先换
			if (x == 0)continue;//如果一个也换不到,那么直接跳过
			if (y == 0)//如果0个就能换,那么就直接加上,肯定要换
				sum += x;
			else
				mp.insert(pair<double, double>(y / x, y));//其他的就按性价比倒数排序
		}
		if (m == 0)sum = sum;//如果0猫粮,那么sum就是该值(防止有0猫粮情况)
		else {
			for (auto it = mp.begin(); it != mp.end(); it++) {
				if (m - (it->second) < 0) {//如果猫粮不够减了
					sum += (m / (it->second)) * (it->second / it->first);//那么取最大百分比
					break;//结束
				} else {
					sum += it->second / it->first;//如果够减,那么就全部算上
					m -= it->second;
				}
			}
		}
		printf("%.3lf
", sum);//保留三位小数
	}
}

尾声

本题带我们熟悉了multimap的使用,同时本题对0的处理也是相当关键,如果想到了排序和对0的处理,那么对于你来说这道题就易如反掌了。

总结

本题为我们提供了新的思路,同时熟悉了multimap的如果觉得笔者写的还不错的话,那么留下您的点赞收藏和关注哦~