障碍滑雪比赛(Slalom,UVa 11627)

AC通道:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2674

障碍滑雪比赛

Description

在一场滑雪比赛中,你需要通过 n 个旗门(均可看成水平线段)。
i 个旗门左端的坐标为 (xi,yi) ,所有旗门的宽度均为 W
旗门海拔高度严格递减。
你有 S 双滑雪板,第 j 双的速度为 sj (即向下滑行速度为 sj 米/秒)。
你的水平速度在任何时刻都不能超过 vh 米/秒,但可以任意变速。
如果起点和终点的水平坐标可以任意选择,用哪些滑雪板可以顺利通过所有旗门?

Input

输入的第一行为数据组数 T
每组数据的第一行为 3 个整数 W vh N 1W108 1vh106 1N105 );
以下 N 行每行为两个整数 xi yi ,即每个旗门左端的坐标( 1xi,yi108 )。
下一行包含一个整数 S ,即滑雪板的数量( 1S106 );
以下 S 行每行一个整数 sj ,即每双滑雪板的速度(1≤s_j≤10^6)。

Output

对于每组数据,输出可以通过所有旗门的滑雪板的最大速度的最小值。

Solution

首先二分答案。
找到最小的一个速度,使得能够通过所有旗门。
自上而下,记录能够走到的坐标的范围。
当当前能够走到的坐标不存在的时候,就表示这个速度不能成立。

Code

[cpp]
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <algorithm>  
  4.   
  5. using namespace std;  
  6.   
  7. int T,n,w,v_h,s,maxv,tt;  
  8. int x[100010],y[100010];  
  9. int v[1000010];  
  10.   
  11. inline double Max(double x,double y){  
  12.     return x>y?x:y;  
  13. }  
  14.   
  15. inline double Min(double x,double y){  
  16.     return x<y?x:y;  
  17. }  
  18.   
  19. bool pan(int speed){  
  20.     double startl=x[n],startr=x[n]+w;  
  21.     for(int i=n-1;i>=1;i–){  
  22.         double tmp=((double)v_h*(y[i+1]-y[i])/speed);  
  23.         startl=Max((double)x[i],startl-tmp);  
  24.         startr=Min((double)x[i]+w,startr+tmp);  
  25.         if(startl>startr)return false;  
  26.     }  
  27.     return true;  
  28. }  
  29.   
  30. inline int in(){    
  31.     int ans=0;    
  32.     char x=getchar();    
  33.     while(x<‘0’||x>‘9’)x=getchar();  
  34.     while(x>=‘0’&&x<=‘9’){ans=ans*10+x-‘0’;x=getchar();}    
  35.     return ans;     
  36. }  
  37.   
  38. int main(){  
  39.     T=in();  
  40.     while(T–){  
  41.         maxv=0;  
  42.         w=in();v_h=in();n=in();  
  43.         for(int i=1;i<=n;i++){x[i]=in();y[i]=in();}  
  44.         s=in();  
  45.         for(int i=1;i<=s;i++)v[i]=in();  
  46.         sort(v+1,v+s+1);  
  47.         maxv=v[s];  
  48.         int ans=0,l=0,r=maxv;  
  49.         while(l<=r){  
  50.             int mid=(l+r)/2;  
  51.             bool flag=pan(mid);  
  52.             if(flag){  
  53.                 if(ans<mid)ans=mid;  
  54.                 if(l!=mid+1)l=mid+1;  
  55.                 else break;   
  56.             }  
  57.             else{  
  58.                 if(r!=mid-1)r=mid-1;  
  59.                 else break;  
  60.             }  
  61.         }  
  62.         if(!ans)printf(“IMPOSSIBLE\n”);  
  63.         else{  
  64.             for(int i=s;i>=1;i–)if(v[i]<=ans){  
  65.                 printf(”%d\n”,v[i]);  
  66.                 goto nxt;  
  67.             }  
  68.             printf(”IMPOSSIBLE\n”);  
  69.         }  
  70. nxt:;  
  71.     }  
  72.     return 0;  
  73. }  

你可能感兴趣的:(二分,贪心)