題意:鐵人雙項比賽由長跑和騎自行車組成,參賽選手必須先完成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; }