Walker
Walker
題意:
一個區間[0,n],區間上有兩個點,坐標分別是pos1,pos2,速度分別是v1,v2,這兩個點是在移動,可以隨時改變移動方向,問當區間的每一塊均被一個點或兩個點移動覆蓋時,最少花費的時間是多少
題解:
介紹一個函數get_dis(pos,v,n):在pos位置覆蓋區間n需要的最短時間
這個最短時間由兩個部分取最小值
一個部分是從pos走到0再返回到n
另一個是從pos走到n再返回到0
我們分類討論情況:
我們著重講第三點,這個匯合點pos怎么確定?
我們先想想,在第三個情況下,兩者我們時間是要先取最大值,然后在最大值里選最小值,也就是兩者所用時間應該越相近越好,這樣可以保證最大化的最小值合理,而確定pos我們當然要用二分
當前的mid使得前者時間大于后者時,mid就應該往左移動,所以r=mid,反之l=mid,進行個100多次二分,這個答案就會非常精確了
以上三種情況取最小輸出
代碼:
#include <bits/stdc++.h> using namespace std;//在pos位置覆蓋到區間n需要的最短時間 double get_dis(double pos,double v,double n) { double a = (pos + n) / v; // 往左走到l再走到n double b = (n - pos + n) / v; //往右走到r再走到n return min(a,b); // 取最小值 }void Solve() {double n,p1,v1,p2,v2;scanf("%lf%lf%lf%lf%lf",&n,&p1,&v1,&p2,&v2);if(p1 > p2){swap(p1,p2);swap(v1,v2);}double ans = 9999999999999999;// 1.自己走完全程用的時間 ans = min(ans , get_dis(p1,v1,n));ans = min(ans , get_dis(p2,v2,n));// 2.相對走完自己的路程 ans = min(ans , max((n-p1)/v1 , p2/v2));// cout<<ans<<endl;double l = p1,r = p2; // 在p1和p2之間尋找一個分界點 for(int i=1;i<=100;i++) // 二分分界點 {double mid = (l + r) / 2; //分界點 double ans1 = get_dis(p1,v1,mid); double ans2 = get_dis(n-p2,v2,n-mid);ans = min(ans,max(ans1,ans2));if(ans1 < ans2) l = mid; // 讓到達分界點的時間盡可能的相同 else r = mid;}printf("%.12f",ans); } int main() {int t;scanf("%d",&t);while(t--){Solve();if(t) puts("");} }/* 2 10000.0 1.0 0.001 9999.0 0.001 4306.063 4079.874 0.607 1033.423 0.847 */總結
- 上一篇: Mine Sweeper II
- 下一篇: Sky Garden