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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值