• bzoj2765 铁人双项比赛


    Description

    铁人双项比赛是吉林教育学院的一项传统体育项目。该项目比赛由长跑和骑自行车组成,参赛选手必须先完成k公里的长跑,然后完成r公里的骑车,才能到达终点。每个参赛选手所擅长的项目不同,有的擅长长跑,有的擅长骑车。如果总赛程s=k+r一定,那么K越大,对擅长长跑的选手越有利;k越小,对擅长骑车的选手越有利。
     
    现在给定总赛程s,以及每个选手长跑和骑车的平均速度,请你求出对于某个指定的选手最有利的k和r。所谓最有利,是指选择了这个k和r后,该选手可以获得冠军,且领先第2名尽量地多。

    Input

    你的程序从文件读入输入数据。
    输入的第一行是两个正整s和n,s表示总赛程(单位为公里,s≤231),n表示参赛总人数(2≤n≤100)。
    接下来的n行每行是两个实数,分别表示每个选手长跑的平均速度和骑车的平均速度(单位为千米/小时)。
    第n个选手就是指定的选手,你的任务是求出对他最有利的k和r。

    Output

    你的程序的输出包括三个数k,r, t,分别表示对第n号选手最有利的k和r(浮点数,保留小数点后2位),以及在选择k和r的情况下,第n号选手最多可以领先第2名多少秒(四舍五入到整数);如果另一个选手和该选手并列第一,则t i=0。倘若无论选择什么k,r都不能使第n号选手获胜,则输出“NO”。

    s确定后,选手完成比赛的时间是关于k的一次函数,图像为直线

    问题为求k使f(k)=(选手1~n-1的最高成绩-选手n成绩)取得最大值

    f(k)的图像为上凸的折线,最大值在折点或两端取得

    枚举每个可能为折点的直线交点求f(k)的最大值

    若数据范围更大可以求半平面交直接处理出折点

    #include<cstdio>
    int n;
    double s;
    double v1,v2;
    double a[105],b[105];
    double km=0,ans=-1.0e50;
    void cal(double x){
        if(x<0||x>s)return;
        double y=1.0e50,c;
        for(int i=1;i<n;i++){
            c=a[i]*x+b[i];
            if(c<y)y=c;
        }
        y-=a[n]*x+b[n];
        if(y>ans)ans=y,km=x;
    }
    int main(){
        scanf("%lf%d",&s,&n);
        for(int i=1;i<=n;i++){
            scanf("%lf%lf",&v1,&v2);
            a[i]=1.0/v1-1.0/v2;
            b[i]=s/v2;
        }
        for(int i=1;i<n;i++){
            for(int j=i+1;j<n;j++){
                cal((b[j]-b[i])/(a[i]-a[j]));
            }
        }
        cal(0);
        cal(s);
        if(ans>=0)printf("%.2lf %.2lf %.0lf",km,s-km,ans*3600.0);
        else puts("NO");
        return 0;
    }
  • 相关阅读:
    下个月去北京了,心如一团乱麻好多事情要解决,但是不知道从哪里开始,还是顺其自然吧,一件件的解决
    C# SQLServer 数据库连接类
    C#页面缓存写法
    从北京站到天通苑怎么走,
    工作描述的介绍|如何写工作描述
    网线制作方法|国标网线制作方法|常用的网线制作方法
    递归删除空文件夹
    如何使用股票行情软件看股票
    正则批量验证函数
    简单的游标更新日期例子
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5173395.html
Copyright © 2020-2023  润新知