Codeforces 703C. Chris and Road
题目链接:http://codeforces.com/problemset/problem/703/C
题意:
在平面上有一个X-Y轴,一人正立于(0, 0)点,他想到达(0, w)点,且只能沿着竖直的向Y正半轴移动,最大速度为 u,可以随时在0 ~ u 之间调整自己的速度,在y = 0 和 y = w之间存在一条路,在路上存在一辆 bus,出人意料,这辆 bus 是一个不规则的凸 n 边形,其只能平行于 X 轴以速度 v 匀速向 X 负半轴移动.人在行动时能被车撞的条件是某时某刻人的坐标在车的坐标所围成的区域之内,也就是说允许与车擦边,给你n, w, v, u, 以及这个奇形怪状的车的 n 个顶点的坐标,问人达到目的地的最短时间.
思路:
慎思之,很是麻烦,但是理清思路之后就好做多了.首先把所有情况分为三种:
情况1:人以最大速度 u ,直接横穿马路,此时车还处于 Y 轴右侧,未触及Y轴,即很幸运的没被车撞.满足这个情况的条件是对于每一点(xi, yi),其与 Y 轴的交点是(0, yi),人到达此点的时间(yi / u)大于等于车到达此点的时间(xi / v);即对于所有的 i,满足 yi / u >= xi / v,也就是说在车到达此点之时,人已经先于车过去了.
情况2:人同样以最大速度 u 横穿马路,此时车已处于 Y 轴左侧,即车在人之前已经过去,那么人肯定就不会被车撞了.满足这个情况的条件是对于每一点(xi, yi),设其与 Y 轴的交点是(0, yi),人到达此点的时间(yi / u)小于等于车到达此点的时间(xi / v);即对于所有的 i,满足 yi / u <= xi / v,也就是说在人到达某一点之前,车已先于人通过此点.
情况3:人要是想以最大速度 u 通过马路,会在某时某刻被撞扑街.那么此时最优的办法就是从一开始,先尽可能远的到达某点 X 处(设时间为t1),在此处等待车过去之后再以最大速度通过(设时间为t2).如果车上某点是(xi, yi),那么设 X 这点是(0, yi),人到达这点的时间是 yi / u,车到达这点的时间是 xi / v,如果满足这种情况,那么说明 xi / v > yi / u,所以t1取较大值为 xi / v,则t2 为 (w - yi) / u,总时间t = t1 + t2.至于此点怎么寻找,因为是否被撞,关键是看车的顶点,那么在O(N)的时间复杂度内枚举每个顶点,取最大值就好了.
至此,所有情况分析完毕.
代码:
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 typedef unsigned long long ULL; 5 using namespace std; 6 7 int main() { 8 int n, w, v, u; 9 scanf("%d%d%d%d", &n, &w, &v, &u); 10 int fast = 0, slow = 0;//初始化假设满足情况1和情况2 11 double t = -1; 12 for(int i = 0; i < n; i++) { 13 int x, y; 14 scanf("%d%d", &x, &y); 15 if(1.0 * x / v < 1.0 * y / u) fast = 1;//存在一点不满足情况1 16 if(1.0 * x / v > 1.0 * y / u) slow = 1;//存在一点不满足情况2 17 t = max(t, 1.0 * x / v + 1.0 * (w - y) / u);//枚举顶点,取最大值 18 } 19 if(!fast || !slow) t = 1.0 * w / u;//满足情况1和情况2之一 20 printf("%.10lf\n", t); 21 return 0; 22 }