FatMouse‘ Trade(贪心算法)

原题链接

Problem Description

FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, 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.

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.

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.

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

单词:

  • warehouse 仓库

题目大意:

肥鼠准备了M磅的猫食,并准备与守卫仓库的猫进行贸易,仓库中有他最喜欢的食物——JavaBean。仓库有N个房间。 第i个房间包含J [i]磅JavaBean,并且需要F [i]磅猫食。 肥鼠不必在房间内交易所有JavaBean,而是如果他支付F [i] * a%的猫食,他可能会得到J [i] * a%的JavaBean。 这是一个实数。 现在,他正在将这项作业分配给你:告诉他可以获取的最大JavaBean数量。
输入包含多个测试用例。 每个测试用例第一行包含两个非负整数M和N。然后是N行,每行分别包含两个非负整数J [i]和F [i],表示仓库中JavaBean的量以及交换JavaBean所需要的猫粮。 最后一个测试用例用两个-1结束。 所有整数均不大于1000。

解法分析:

he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food——该句说明猫粮和肥鼠喜欢的JavaBean可以按比例交换(优先选择当前来看使用较少的猫粮可以得到较多JavaBean的仓库)。进而可以得到本题是一道经典的贪心算法 — greedy algorithm

  • 贪心算法的思想:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解
  • 那么,如何贪心呢?答:选择性价比较高的仓库,即优先选择JavaBean / 猫食所得比值较大的仓库。可以用一个结构体数组来计算性价比。

样例分析:

5 3
7 2
4 3
5 2

对于以上样例,M = 5(猫粮),N = 3,随后有三行数据。7、4、5分别表示仓库里的JavaBean,2、3、2分别表示交换JavaBean所需要的猫粮。因此,三个仓库的性价比分别为7/2=3.5、4/3=1.333、5/2=2.5。故按照优先选择第一个仓库,然后选择第三个仓库,最后选择第二个仓库的贪心策略可以得到最优解,即可以获取最多的JavaBean。贪心的过程如下:

  • 先付出2单位的猫粮,换取第一个仓库的7单位的JavaBean。此时肥鼠还剩3单位的猫粮
  • 再付出2单位的猫粮,换取第二个仓库的5单位的JavaBean。此时肥鼠还剩1单位的猫粮并且已经得到了12单位的JavaBean
  • 最后用仅剩的1单位的猫粮去性价比最低的仓库,可以得到4/3=1.333单位的JavaBean。故最后肥鼠可以得到13.333单位的JavaBean。
  • 第二个样例同理
  • 最后还需要注意:结构体里面全都定义为double类型, 防止两数相除丢失精度

AC参考代码:

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

struct xjb//性价比结构体
{
    double j;//javabean
    double c;//catfood
    double d;//表示性价比javabean/catfood
}nums[1010];

bool cmp(xjb u,xjb v)
{
    return u.d > v.d;//按照性价比高的排序
}

int main()
{
    int m,n;
    while (scanf("%d%d",&m,&n) != EOF)
    {
        if (m == -1 && n == -1) break;
        
        for (int i = 0;i < n;i++)//接收n行数据
        {
            scanf("%lf%lf",&nums[i].j,&nums[i].c);
            nums[i].d = nums[i].j / nums[i].c;//计算性价比
        }
        
        sort(nums,nums + n,cmp);
        
        double ans = 0;//表示可以得到的最多javabean
        for (int i = 0;i < n;i++)//对所有的结构体数组进行遍历
        {
            if (m > nums[i].c)//当前所剩的猫粮数量大于性价比最高的仓库所需要的猫粮数量
            {
                ans += nums[i].j;//javabean的数量加上这个仓库的所有javabean
                m -= nums[i].c;//兑换之后猫粮减少
            }
            else//当前所剩的猫粮不足以兑换全部的javabean则按照比例交换 
            {
                ans += (nums[i].d * m);
                break;//猫粮全部使用完,结束循环
            }
        }
        printf("%.3lf\n",ans);
    }
    return 0;
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值