您的位置:首页 > 其它

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

2016-03-06 17:12 429 查看
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(1≤W≤108,1≤vh≤106,1≤N≤105);

以下 N 行每行为两个整数 xi 和 yi,即每个旗门左端的坐标(1≤xi,yi≤108)。

下一行包含一个整数 S,即滑雪板的数量(1≤S≤106);

以下 S 行每行一个整数 sj,即每双滑雪板的速度(1≤s_j≤10^6)。

Output

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

Solution

首先二分答案。

找到最小的一个速度,使得能够通过所有旗门。

自上而下,记录能够走到的坐标的范围。

当当前能够走到的坐标不存在的时候,就表示这个速度不能成立。

Code

[cpp] #include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int T,n,w,v_h,s,maxv,tt;
int x[100010],y[100010];
int v[1000010];

inline double Max(double x,double y){
return x>y?x:y;
}

inline double Min(double x,double y){
return x<y?x:y;
}

bool pan(int speed){
double startl=x
,startr=x
+w;
for(int i=n-1;i>=1;i–){
double tmp=((double)v_h*(y[i+1]-y[i])/speed);
startl=Max((double)x[i],startl-tmp);
startr=Min((double)x[i]+w,startr+tmp);
if(startl>startr)return false;
}
return true;
}

inline int in(){
int ans=0;
char x=getchar();
while(x<‘0’||x>‘9’)x=getchar();
while(x>=‘0’&&x<=‘9’){ans=ans*10+x-‘0’;x=getchar();}
return ans;
}

int main(){
T=in();
while(T–){
maxv=0;
w=in();v_h=in();n=in();
for(int i=1;i<=n;i++){x[i]=in();y[i]=in();}
s=in();
for(int i=1;i<=s;i++)v[i]=in();
sort(v+1,v+s+1);
maxv=v[s];
int ans=0,l=0,r=maxv;
while(l<=r){
int mid=(l+r)/2;
bool flag=pan(mid);
if(flag){
if(ans<mid)ans=mid;
if(l!=mid+1)l=mid+1;
else break;
}
else{
if(r!=mid-1)r=mid-1;
else break;
}
}
if(!ans)printf(“IMPOSSIBLE\n”);
else{
for(int i=s;i>=1;i–)if(v[i]<=ans){
printf(”%d\n”,v[i]);
goto nxt;
}
printf(”IMPOSSIBLE\n”);
}
nxt:;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分 贪心