zoukankan      html  css  js  c++  java
  • 【BZOJ】【2765】【JLOI2010】铁人双项比赛

    计算几何/半平面交


      本来我是想去写POJ 1755的,然后想起了这道跟它很像的题,但应该是弱化版,所以就先写了这个……

      我们可以发现每个人的总用时,与k是呈一次函数关系的:$time_i=frac{k}{Vrun_i}+frac{S-k}{Vride_i}$

      然而我们要找的是某个k,使得$min(time_n-time_i)$最大

      那么就是一个线性规划问题了……这个也可以用半平面交来做……(蒟蒻并不会单纯形)

      下面的部分为了偷懒简洁我就用$a_i$和$b_i$来代替两种速度……

      我一开始想的做法是:维护一个$y=(frac{1}{a_i}-frac{1}{b_i})*x+frac{S}{b_i}$的最小值(上凸壳?),然后由于线性分段函数的极值一定在分界点处取到(BZOJ 1038 瞭望塔),所以可以枚举分界点计算答案。

      然而不会写……后来膜拜了lyd神犇的代码,发现:

        这题$nleq 100$,所以找到可能成为分界点的点,即所有直线的交点,暴力更新答案就好了……

        然后还有一个地方是将不等式重新变形了一下,将第n条直线直接减到前面n-1条直线中……

      无限ym……

     1 /**************************************************************
     2     Problem: 2765
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:40 ms
     7     Memory:1276 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 2765
    11 #include<cmath>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #include<iomanip>
    18 #define rep(i,n) for(int i=0;i<n;++i)
    19 #define F(i,j,n) for(int i=j;i<=n;++i)
    20 #define D(i,j,n) for(int i=j;i>=n;--i)
    21 using namespace std;
    22  
    23 const int N=110;
    24 /*******************template********************/
    25 typedef long double lf;
    26 #define eps 1e-12
    27 int n,num;
    28 lf a[N],b[N],c[N],d[N],S,anst,ansk;
    29  
    30 void calc(lf k){
    31     lf t=1e100;
    32     F(i,1,n-1) t=min(t,k*c[i]+d[i]);
    33     if (t>anst) anst=t,ansk=k;
    34 }
    35  
    36 int main(){
    37 #ifndef ONLINE_JUDGE
    38     freopen("2765.in","r",stdin);
    39 //  freopen("2765.out","w",stdout);
    40 #endif
    41     cin >>S>>n;
    42     F(i,1,n) cin >> a[i] >> b[i];
    43     F(i,1,n-1){
    44         c[i]=1/a[i]-1/b[i]-1/a[n]+1/b[n];
    45         d[i]=S/b[i]-S/b[n];
    46     }
    47  
    48     anst=-1e100;
    49     F(i,1,n-1) F(j,i+1,n-1){
    50         if (fabs(c[i]-c[j])<eps) continue;
    51         lf k=(d[j]-d[i])/(c[i]-c[j]);
    52         if (k<eps || k>S-eps) continue;
    53         calc(k);
    54     }
    55     calc(0); calc(S);
    56     anst*=3600;
    57     if (anst<-eps) puts("NO");
    58     else{
    59         if (anst<eps) anst=0;
    60         cout<<setprecision(2)<<fixed<<ansk<<' '<<S-ansk<<' ';
    61         cout<<setprecision(0)<<fixed<<anst<<endl;
    62     }
    63     return 0;
    64 }
    View Code

    2765: [JLOI2010]铁人双项比赛

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 477  Solved: 117
    [Submit][Status][Discuss]

    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”。

    Sample Input

    100 3
    10.0 40.0
    20.0 30.0
    15.0 35.0

    Sample Output

    14.29 85.71 612

    HINT

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    剑指 Offer 60. n个骰子的点数
    剑指 Offer 59
    剑指 Offer 59
    剑指 Offer 58
    剑指 Offer 58
    AndroidStudio中提示:Didn't find class "android.support.v7.widget.RecyclerView"
    SpringBoot中通过重写WebMvcConfigurer的addCorsMapping方法实现后台服务解决跨域问题
    Android中使用Room时怎样存储带list集合的对象
    Android中在使用Room时提示:Cannot figure out how to save this field into database. You can consider adding a type converter for
    Android中ListView的使用以及使用适配器设置数据源
  • 原文地址:https://www.cnblogs.com/Tunix/p/4499876.html
Copyright © 2011-2022 走看看