猫鼠交易(贪心) HDU 1009 FatMouse' Trade

猫鼠交易(贪心) HDU 1009 FatMouse’ Trade

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

这里我就参考别人的翻译了一下:

猫鼠交易

题目描述:
胖老鼠准备了M榜的猫食,想要用来与守卫藏有他最爱的JavaBean的仓库的猫猫们进行交易。
仓库有N个房间,第i个房间里面有J[i]榜的JavaBean,同时需要F[i]榜的猫食才能换取。
胖老鼠可以只按比例换取JavaBean而不是换取整个房间的JavaBean。
现在它把交易计划交给你来处理:告诉它,它最多能得到多少榜JavaBean。

输入说明:
允许多次案例输入,每个案例的第一行为两个无符号整数 M和N。
接着是N行输入,每一行包含无符号整数J[i]和F[i]。
程序输入以两个-1结束。
所有的整数都不会超过1000。

输出说明:
对于每个案例,输出一个保留三位有效数字的实数,用来表示这个案例中胖老鼠最大能获得的JavaBean。

个人分析:

上面我把这个题的题意解释了一遍,采用贪心的思考问题方法
即“做出的是在某种意义上的局部最优解”,对于本题来说,局部最优解就是整体最优解,因此采用贪心法。
很显然,要采用结构体做,那么我们申明结构体一般还要写好cmp方法,并且是重载的cmp方法 具体如下:

struct node
{
    int j;
    int f;
    double rate;
}fm[1008];

int cmp(node x,node y)
{
    return x.rate>y.rate;
}

要使JavaBean最大,那就得要每一榜猫食换取尽可能多的JavaBean。
所以 先计算出每一个房间的 单位食物能换取的JavaBean,即 rate[i] = J[i]/F[i]。
接着 对结构体fm(肥鼠)排序,rate[i]越大,JavaBean换的越多
剩余的JavaBean小到不足以换取整个房间的JavaBean时,选择按比例换取JavaBean。(也就是剩余的m去乘rate[i]那个比例) 如下关键代码:

 sort(fm,fm+n,cmp);
        for(int i=0;i<n;i++)
        {
            if(m>=fm[i].f)
            {
                m-=fm[i].f;
                sum+=fm[i].j;
            }
            else
            {
                sum+=fm[i].rate*m;
                break;
            }
        }

对以上代码解释:
m是这只肥鼠所有的猫粮 通过比例排序(从大到小排)比例大的那么我们获得的豆子也就越多 只要m>=fm[i].f 那么我们可以获得全部的豆子 剩余的m不足以获得全部的豆子我们用比例来拿 sum+=fm[i].rate*m; 但是注意拿了之后要break 因为已经拿完了 不然还会继续循环的。。。这里要注意

个人感受:

这个贪心也是我第一次遇到,觉得很不可思议,因为这个题是通过比例来求解的,看来要走的路还挺长的,虽然走的很慢,但还是要坚持下去!
具体代码如下:
AC

#include
#include
#include
using namespace std;
struct node
{
    int j;
    int f;
    double rate;
}fm[1008];

int cmp(node x,node y)
{
    return x.rate>y.rate;
}
int main()
{
    int m,n;
    while(cin>>m>>n&&m!=-1&&n!=-1)
    {
        double sum=0;
        for(int i=0;i<n;i++)
        {
            cin>>fm[i].j>>fm[i].f;
            fm[i].rate=(double)fm[i].j/fm[i].f;
        }
        sort(fm,fm+n,cmp);
        for(int i=0;i<n;i++)
        {
            if(m>=fm[i].f)
            {
                m-=fm[i].f;
                sum+=fm[i].j;
            }
            else
            {
                sum+=fm[i].rate*m;
                break;
            }
        }
        printf("%.3lf\n",sum);
    }


    return 0;
}
学如逆水行舟,不进则退

你可能感兴趣的:(算法)