Slalom

题意描述比较恶心,首先需要明确题目给出的坐标描述的不是类似横版游戏的纵切图,实际上把整个斜面当做一个平面,详细说明见图,N个宽度为W的”门“, 横向移动的速度不能超过vh, S个速度为v[i]的滑雪板,滑雪板的速度是纵向移动的速度,完成比赛必须通过所有的门,求能够完成比赛的速度最快滑雪板的速度

Slalom_第1张图片


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string> 
#include <sstream>
#include <utility>
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::greater;

const int MAXN(100010);

int x[MAXN], y[MAXN];
int v[1000010];

bool legal(int goal, int W, int vh, int N)
{
	double x1 = x[0], x2 = x[0]+W;
	for(int i = 1; i < N; ++i)
	{
		double excur = double(y[i]-y[i-1])/goal*vh;
		x1 -= excur;
		x2 += excur;
		if(x[i] > x2 || x[i]+W < x1)
			return false;
		x1 = max(x1, double(x[i]));
		x2 = min(x2, double(x[i]+W));
	}
	return true;
}

int main()
{
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int W, vh, N;
		scanf("%d%d%d", &W, &vh, &N);
		for(int i = 0; i < N; ++i)
			scanf("%d%d", x+i, y+i);
		int S;
		scanf("%d", &S);
		for(int i = 0; i < S; ++i)
			scanf("%d", v+i);
		sort(v, v+S);
		int l = 0, r = S;
		while(l < r)
		{
			int m = (l+r) >> 1;
			if(legal(v[m], W, vh, N))
				l = m+1;
			else
				r = m;
		}
		if(l)
			printf("%d\n", v[l-1]);
		else
			printf("IMPOSSIBLE\n");
	}
	return 0;
}


你可能感兴趣的:(Slalom)