题意:铁人双项比赛由长跑和骑自行车组成,参赛选手必须先完成k千米的长跑,而后完成r千米的骑车,才能到达终点。参赛选手有的擅长长跑,有的擅长骑车。spa
若是总赛程s=k+r必定,那么K越大,对擅长长跑的选手越有利;k越小,对擅长骑车的选手越有利。code
如今给定总赛程s,以及每一个选手长跑和骑车的平均速度,请你求出对于某个指定的选手最有利的k和r。blog
所谓最有利,是指选择了这个k和r后,该选手能够得到冠军,且领先第2名尽可能地多。ci
讲道理这题应该有SpecialJudge,可是BZOJ是在有多种方案时输出k最小的方案,题面上还没说…WA了一屏....it
并不知道半平面交是什么东西(半瓶面胶),我写的是二分答案…首先咱们把速度的单位从 公里/小时 转为 秒/公里,而后用i号选手的骑车速度减去n号选手的骑车速度,就表示i号选手和n号选手同时骑单位长度的车,n号选手会领先i号选手多少秒(负值表示n号选手落后i号选手).io
接下来咱们会发现,若是每长跑1公里n号选手会领先i号选手v1秒,每骑1公里车n号选手会领先i号选手v2秒(v1,v2都可能为负),二分答案时要求n号选手必须领先i号选手很多于ans秒,咱们就能够肯定一个关于k的不等式k*v1+(s-k)*v2>=ans,这里只有k未知,因此能够解出这个不等式.class
每二分一个答案,一共获得n-1个形如”k>a”或”k<b”的不等式,只要判断这个不等式组有没有解便可.注意v1==v2的地方须要特判.最后必定要注意:输出解的时候k尽可能小,因此最后利用二分出的答案解一遍不等式组,输出的时候用k的下界输出..di
#include<cstdio> #include<algorithm> using namespace std; const int maxn=105; double v1[maxn],v2[maxn]; int s,n; bool check(double ans){ double upper=s,lower=0; for(int i=1;i<n;++i){ if(v1[i]==v2[i]){ if(s*v1[i]<ans)return false; } else if(v1[i]<v2[i])upper=min(upper,(ans-v2[i]*s)/(v1[i]-v2[i])); else lower=max(lower,(ans-v2[i]*s)/(v1[i]-v2[i])); } return upper>=lower; } void work(double ans){ double upper=s,lower=0; for(int i=1;i<n;++i){ if(v1[i]==v2[i])continue; else if(v1[i]<v2[i])upper=min(upper,(ans-v2[i]*s)/(v1[i]-v2[i])); else lower=max(lower,(ans-v2[i]*s)/(v1[i]-v2[i])); } printf("%.2f %.2f ",lower,s-lower); } int main(){ scanf("%d%d",&s,&n); for(int i=1;i<=n;++i){ scanf("%lf%lf",v1+i,v2+i); v1[i]=3600/v1[i];v2[i]=3600/v2[i]; } for(int i=1;i<n;++i){ v1[i]-=v1[n];v2[i]-=v2[n]; } double l=-1,r=1e50; while(r-l>=1e-8){ double mid=(l+r)/2.0; if(check(mid))l=mid; else r=mid; } if(r<0)printf("NO\n"); else{ work(r); printf("%.0f\n",r); } return 0; }