[算法][ACM]hdoj 1009 FatMouse' Trade

解决肥老鼠用猫粮换取JavaBeans的问题,通过计算各仓库JavaBeans的性价比,并使用排序算法找到最优交换方案。
Problem Description:
FatMouse prepared M pounds of cat food, ready to trade with thecats guarding the warehouse containing his favorite food,JavaBean.
The warehouse has N rooms. The i-th room contains J[i] pounds ofJavaBeans and requires F[i] pounds of cat food. FatMouse does nothave to trade for all the JavaBeans in the room, instead, he mayget J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of catfood. Here a is a real number. Now he is assigning this homework toyou: tell him the maximum amount of JavaBeans he can obtain.
Input:
The input consists of multiple test cases. Each test case beginswith a line containing two non-negative integers M and N. Then Nlines follow, each contains two non-negative integers J[i] and F[i]respectively. The last test case is followed by two -1's. Allintegers are not greater than 1000.
Output:
For each test case, print in a single line a real number accurateup to 3 decimal places, which is the maximum amount of JavaBeansthat FatMouse can obtain.
题目大概翻译:
肥老鼠有M磅猫粮,想要和看守仓库的猫交换他最喜欢的JavaBean。仓库一共有N间,第i间仓库里包含J[i]磅的JavaBeans,想要得到这些JavaBeans需要付出F[i]磅猫粮作为代价。肥老鼠不必得到房间里所有的JavaBeans。他可以用这个房间需要的猫粮数F[i]的a%,来交换这个房间拥有的JavaBeans数J[i]的a%。需要你计算出肥老鼠最多能够得到多少JavaBeans。
输入大概翻译:
输入将包含多组数据,每一组数据将以两个非负整数M 
N开始,然后有N行数据,包含两个非负整数J[i]和F[i]。出现两个-1表示测试数据结束。所有的整数都不超过1000
输出大概翻译:
对于每一个测试数据的情况,输出单独的一行(精确到小数点后三位数)来表示这个肥老鼠可以得到的JavaBeans的最大值。

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

因为本题想要求解的是肥老鼠最后能的得到的最多的JavaBeans的值。所以我们就要尽量可能的在每个房间拿到多的而且便宜的JavaBeans。因此选择贪心算法。

如何界定便宜,不妨换一个想法,也就是性价比,单位重量的猫粮换到的JavaBeans越多就说明越实惠。
基于这个想法,我就想设定一个变量来保存每个房间的实惠情况。同时为了方便对变量进行有效的管理,在这里我选择将一个房间内的需要的猫粮数、拥有的JavaBeans数、以及实惠情况同意储存在一个struct中。


struct food{
    int j,f;
    double p;
}food_N[MAX];
p表示实惠程度,我选择了用结构数组来表示这个大仓库,每一间小房间就是一个结构体,因为题目中要求每个整数的值都不超过1000因此将整个仓库的大小设置为1000(这样做是使用了food_N[0],如果不想使用food_N[0]数组则需要声明为1001),实惠程度的具体计算方法:

food_N[i].p=(double)food_N[i].j/food_N[i].f;//这里的i表示第i个房间。

在计算出实惠程度之后,因为肥老鼠的目的是得到最多的JavaBeans因此我们需要找出最实惠的房间多换取一点JavaBeans。所以下一步我们需要将实惠程度进行由大到小的排序。首先选择比较笨拙的冒泡排序法,发现效率一般般的冒泡排序法竟然没有超时,这个让我很惊讶

for(int i=0;i<n;i++)
        {
            for(int j=i;j<n;j++)
            {
                if(food_N[i].p<food_N[j].p)
                {
                    temp=food_N[i];
                    food_N[i]=food_N[j];
                    food_N[j]=temp;
                }
            }
        }//这里的n表示总得房间数。

接下来是基于C++的sort排序

sort(food_N,food_N+n,check);
明显代码简洁了很多。

现在实惠程度的排序也已经完成了,可以让肥老鼠去换了,按照实惠程度从最实惠的一个房间开始换走最实惠房间内的所有JavaBeans依次向下进行,直到自己的猫粮用完。如果出现猫粮不足以完全换走JavaBeans的情况时,本着有多少换多少的原则进行即可。

for(int i=0;i<n;i++)
        {
            if(m>food_N[i].f)
            {
                sum+=food_N[i].j;
                m-=food_N[i].f;
            }
            else
            {
                sum+=food_N[i].p*m;
                break;
            }
        }//这里的m表示肥老鼠拥有的猫粮数目,sum表示肥老鼠可以得到的猫粮总和
一旦肥老鼠的猫粮用完了立刻用break来跳出循环。

本题目的完整代码(冒泡版):

#include <stdio.h>
#include <stdlib.h>
#define MAX 1000
struct food{
    int j,f;
    double p;
}food_N[MAX];

int main(void)
{
    int m,n;
    while(scanf("%d%d",&m,&n) && (m!=-1 || n!=-1))
    {
        double sum=0.0;
        struct food temp;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&food_N[i].j,&food_N[i].f);
            food_N[i].p=(double)food_N[i].j/food_N[i].f;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=i;j<n;j++)
            {
                if(food_N[i].p<food_N[j].p)
                {
                    temp=food_N[i];
                    food_N[i]=food_N[j];
                    food_N[j]=temp;
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            if(m>food_N[i].f)
            {
                sum+=food_N[i].j;
                m-=food_N[i].f;
            }
            else
            {
                sum+=food_N[i].p*m;
                break;
            }
        }
        printf("%.3lf\n",sum);
    }
    return 0;
}

本题完整代码(sort版):

#include <stdio.h>
#include <algorithm>
#define MAX 1000
using namespace std;
struct food{
    int j,f;
    double p;
}food_N[MAX];
bool check(struct food n,struct food m);

int main(void)
{
    int m,n;
    while(scanf("%d%d",&m,&n) && (m!=-1 || n!=-1))
    {
        double sum=0.0;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&food_N[i].j,&food_N[i].f);
            food_N[i].p=(double)food_N[i].j/food_N[i].f;
        }
        sort(food_N,food_N+n,check);
        for(int i=0;i<n;i++)
        {
            if(m>=food_N[i].f)
            {
                sum+=food_N[i].j;
                m-=food_N[i].f;
            }
            else
            {
                sum+=food_N[i].p*m;
                break;
            }
        }
        printf("%.3lf\n",sum);
    }
    return 0;
}
bool check(struct food n,struct food m)
{
    return n.p>m.p;
}


本人两个博客,另外一个博客地址为:http://blog.sina.com.cn/yjrjcorpor

内容概要:本文介绍了一款针对红米K30(代号phoenix)定制的原生RisingOS xt操作系统固件,基于安卓16版本,提供支持线刷的fast模式双版本(含root权限)。该固件通过百度网盘分享,包含下载链接和提取码,强调系统未内置文件管理器,用户需在刷机完成后手动安装相关应用。; 适合人群:熟悉刷机操作、具备一定Android系统定制经验的进阶用户或开发者;适用于希望体验原生系统流畅性并获取root权限的红米K30用户。; 使用场景及目标:①为红米K30用户提供轻量化、接近原生安卓的系统体验;②通过root权限实现深度自定义与高级功能控制;③利用fast线刷方式快速完成系统升级或修复。; 阅读建议:刷机前请确保设备型号完全匹配(phoenix),备份重要数据,确认已解锁Bootloader并了解风险;刷机后注意自行安装必要的工具应用如文件管理器,以保证系统完整可用。1-----刷写前提是手机必须解锁bl先。而且会在fast模式刷写固件2-----刷写方法与官方刷写步骤一样3-----此固件为定制初始固件。可以在fast模式刷写4-----属于适配固件。也许有个别bug。不接受请勿下载5-----需要一定的刷机常识与动手能力的友友刷写。6-----资源有可复制性。下载后不支持退。请知悉7-----定制其他需求可以在csdn私信博主参考博文了解详细:https://csdn9.blog.csdn.net/article/details/151715205?spm=1001.2015.3001.5352
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值