题目大意:在一场滑雪比赛中要通过n个门,给出每个门的坐标(xi,yi)。数据给出w(每个门的宽度),v(水平方向上的最大速度,即x轴),以及n。然后是n行门的坐标。在给出m,表示有m双滑雪鞋,每双鞋的速度为s[i]。问说可以通过所有旗门的滑雪板的最大速度。
解题思路:首先现将s[i]排序,然后二分答案。判断只需要更具前后两个旗门的高度差来计算时间,由上一个可达区间推出下一个可达区间,然后加以判断。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 1000005;
const double eps = 1e-9;
struct state {
int x, y;
}d[N];
int n, w, v, m, s[N];
inline void scan_d(int &ret) {
char c; ret = 0;
while((c = getchar()) < '0'|| c >'9');
while(c >= '0' && c <= '9') ret = ret * 10 + (c - '0'), c = getchar();
}
void init() {
scanf("%d%d%d", &w, &v, &n);
for (int i = 0; i < n; i++) scanf("%d%d", &d[i].x, &d[i].y);
scanf("%d", &m);
for (int i = 0; i < m; i++) scanf("%d", &s[i]);
sort(s, s + m);
}
bool judge(int vh) {
double l = d[n - 1].x, r = d[n - 1].x + w;
for (int i = n - 2; i >= 0; i--) {
int tmp = d[i + 1].y - d[i].y;
double ti = (double)tmp / vh;
l -= ti * v; r += ti * v;
if (d[i].x + w < l) return false;
if (d[i].x > r) return false;
if (d[i].x - l > eps) l = d[i].x;
if (d[i].x + w - r < eps) r = d[i].x + w;
}
return true;
}
bool solve() {
if (!judge(s[0])) return false;
if (judge(s[m - 1])) {
printf("%d\n", s[m - 1]);
return true;
}
int l = 0, r = m;
while (true) {
if (r - l == 1) break;
int mid = (l + r) / 2;
if (judge(s[mid])) l = mid;
else r = mid;
}
printf("%d\n", s[l]);
return true;;
}
int main () {
int cas;
scanf("%d", &cas);
while (cas--) {
init();
if (solve() == false) printf("IMPOSSIBLE\n");
}
return 0;
}