zoukankan      html  css  js  c++  java
  • 2016级算法第一次练习赛-F.AlvinZH的儿时梦想——机器人篇

    864 AlvinZH的儿时梦想----机器人篇

    题目链接:https://buaacoding.cn/problem/868/index

    思路

    中等题。

    判断无限玩耍: (p) 的值能够承担的起所有机器的消耗。即比较 (sum_{i=1}^{n}a_i)(p) 的大小。

    分析

    本题有两种解法。

    方法一:二分。

    即二分枚举最长时间,判断充电器能否支撑此时间所有的耗能,不断缩小时间范围,最后可求得答案。难点在判断函数,比较在当前时间条件下,所有需要充电的机器需要的能量能量总和与充能器提供的能量总和,每次需要遍历一次数组。

    方法二:贪心

    感谢李析航同学。这道题还有另外一种想法,结构体排序+贪心。

    把所有机器在不充电时能用的时间算出来(假设第 (i) 个设备能用 (t_i) 秒),对时间进行升序排序。让时间短的设备先充电,让尽可能多的机器能用更长的时间,这就是贪心所在。

    假设已经保证前m个机器玩耍时间达到 (t_m)(即所有机器至少可以玩耍 (t_m),初始值为 (t_0) ),前m个机器耗能效率 (A_m=sum_{i=1}^{m}a_i) 。现在判断充电能否让玩耍时间延长到 (t_{m+1}) ,如果不能,说明答案 (ans) 就在 (t_m)(t_{m+1}) 之间。

    由于已经满足前m个机器玩耍时间达到 (t_m),为了方便计算,我们假设充电器一直在充电,那么多余的电量设为 (power),令 (x=ans-t_m),则有 (power+p_x=A_m) 。解得 (x=frac{power}{A_m-p})(ans=x+t_m)

    还有一种情况,就是已经满足n的机器玩耍时间达到 (t_n) 了,这时可以直接计算x就可以得到答案了。

    参考代码(解法一)

    //
    // Created by AlvinZH on 2017/9/30.
    // Copyright (c) AlvinZH. All rights reserved.
    //
    
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<map>
    #include<cstdlib>
    #include<cmath>
    #include<string>
    #include<algorithm>
    #include<set>
    #include<stack>
    #include<queue>
    #include<utility>
    #define INF 0x3f3f3f3f
    #define eps 1e-8
    #define MaxSize 100005
    typedef long long LL;
    
    using namespace std;
    
    int n, p;
    int A[MaxSize], B[MaxSize];
    
    bool judge(double t)
    {
        double inPower = 1.0 * p * t;//可充电总量
        double needPower;
        for (int i = 0; i < n && inPower > eps; i++) {
            needPower = A[i] * t - B[i];//每个机器需要的充电量
            if (needPower > eps)
                inPower -= needPower;
        }
        if (inPower < eps) return false;
        else return true;
    }
    
    int main()
    {
        while (~scanf("%d %d", &n, &p))
        {
            LL sumA = 0;
            for (int i = 0; i < n; i++) {
                scanf("%d %d", &A[i], &B[i]);
                sumA += (LL)A[i];
            }
    
            if (sumA <= p) printf("Great Robot!
    ");
            else
            {
                double ltime = 0.0, rtime = 1e12, mid, ans;
                while (rtime - ltime >= eps)
                {
                    mid = (ltime + rtime) / 2.0;
                    if (judge(mid))
                    {
                        ltime = mid;
                        ans = mid;
                    }
                    else rtime = mid;
                }
    
                printf("%.3lf
    ", ans);
            }
        }
    }
    

    参考代码二

    //
    // Created by AlvinZH on 2017/9/30.
    // Copyright (c) AlvinZH. All rights reserved.
    //
    
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<map>
    #include<cstdlib>
    #include<cmath>
    #include<string>
    #include<algorithm>
    #include<set>
    #include<stack>
    #include<queue>
    #include<utility>
    #define INF 0x3f3f3f3f
    #define eps 1e-8
    #define MaxSize 100005
    typedef long long LL;
    
    using namespace std;
    
    int n, p, b;
    struct Robot {
        int a;
        double t;
    
        bool operator < (const Robot& r) const {
            return t < r.t;
        }
    };
    
    Robot R[MaxSize];
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
        //freopen("outme.txt", "w", stdout);
        while (~scanf("%d %d", &n, &p))
        {
            LL sumA = 0;
            for (int i = 0; i < n; i++) {
                scanf("%d %d", &R[i].a, &b);
                sumA += (LL)R[i].a;
                R[i].t = b * 1.0 / R[i].a;
            }
    
            if (sumA <= p) printf("Great Robot!
    ");
            else
            {
                sort(R, R + n);
                double ans = R[0].t;//最小玩耍时间
                double power = R[0].t * p;//初始剩余能量
                double timeX;//时间差
                double x;//续命时间
                sumA = R[0].a;//需要充电机器的总功率
    
                int i = 1;
                while(i < n)
                {
                    timeX = R[i].t - ans;
                    if(sumA > p)//需要充电
                    {
                        x = power / (sumA - p);
                        if(x <= timeX)//无法坚持到R[i]充电
                        {
                            printf("%.3f
    ", ans + x);
                            break;
                        }
                    }
    
                    power = power + timeX * (p - sumA);//计算剩余能量
                    sumA += R[i].a;
                    ans = R[i].t;
                    i++;
                }
                if(i == n)//全部机器都要充电
                {
                    x = power / (sumA - p);
                    printf("%.3f
    ", ans + x);
                }
            }
        }
    }
    
  • 相关阅读:
    商品详情的图片添加水印
    ElasticSearch 简单的crud查询
    java产生随机数的三种方式
    springboot+mybatis集成分页功能
    springboot集成swagger文档
    springboot项目根据不同的环境启动不同的配置,如开发环境dev,测试环境sit,生产环境application
    解释器模式
    中介者模式
    访问者模式
    x01.FileProcessor: 文件处理
  • 原文地址:https://www.cnblogs.com/AlvinZH/p/7698983.html
Copyright © 2011-2022 走看看