Morgan Stanley Programming Constest 2014题目Free Fall

题目原文已经找不到了,大体的内容如下:

以地面为y=0建立坐标,有人从(0,H)向下落,途中有些平台,人落到平台上会立刻失去所有速度。人可以从平台两端以水平初速度V往下跳,下跳过程服从平抛运动,V最小为0.001,最大不超过Vmax。给定H,Vmax以及所有平台左端点坐标和长度,求人下落到地面y=0的最短时间。


思路

对每个平台,维护一个最短到达时间的变量。

从最高的平台开始,对每个平台Platform[i],找出从该平台出发能到达的平台Platform[j],更新Platform[j]的最短到达时间为原有最短到达时间Tj与Platform[i]的到达时间Ti+Sqrt(2(Hi-Hj)/g)的较小者。

对每个平台计算能到达平台时,用“允许速度区间”的方法处理高处平台对底处平台的遮挡。


代码实现

#include <iostream>
#include <list>
#include <iomanip>
#include <vector>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <cmath>
#include <ctime>

typedef std::pair<double, double> Interval;

class Platform
{
public:
	double leftBoundary;
	double rightBoundary;
	double height;
	double velocity;
	double timeUsed;
	int prevPlatform;
	int code;
	char direction;

	Platform(int code, double x, double y, double w)
	{
		this->code = code;
		leftBoundary = x;
		rightBoundary = x + w;
		height = y;
		timeUsed = 1e30;
	}

	bool operator < (const Platform& other)
	{
		return height > other.height || height == other.height && code < other.code;
	}

	bool operator >= (const Platform& other)
	{
		return !(*this < other);
	}
};

class Game
{
	const double g = 9.8;
	double maxVelocity;
	double height;
	std::vector<Platform> platforms;
public:
	Game(std::ifstream& fin)
	{
		fin >> height;
		fin >> maxVelocity;
		fin.get();
		std::list<Platform> tempPlatforms;
		int i = 0;
		double x, y, w;

		while (!fin.eof() && fin.peek() != '\n' && fin.peek() != ';')
		{
			fin >> x >> y >> w;
			fin.get();
			tempPlatforms.push_back(Platform(i, x, y, w));
			i++;
		}
		while (!fin.eof() && fin.get() != ';');
		tempPlatforms.push_back(Platform(-1, -1e100, 0, 2e100));
		std::copy(tempPlatforms.begin(), tempPlatforms.end(), std::back_inserter(platforms));
		platforms[0].timeUsed = 0;
		std::sort(platforms.begin(), platforms.end());
	}

private:
	void calculateTime()
	{
		unsigned int i = 0;
		while (i < platforms.size() && platforms[i].code != 0)
			i++;
		while (i < platforms.size())
		{
			std::list<Interval> leftIntervals;
			std::list<Interval> rightIntervals;
			leftIntervals.push_back(Interval(0.001, maxVelocity));
			rightIntervals.push_back(Interval(0.001, maxVelocity));
			for (unsigned int j = i + 1; j < platforms.size() && !(leftIntervals.empty() && rightIntervals.empty()); j++)
			{
				double deltaHeight = platforms[i].height - platforms[j].height;
				if (fabs(deltaHeight) < 1e-10)
					continue;
				double deltaTime = sqrt(2 * deltaHeight / g);
				if (!leftIntervals.empty() && platforms[j].leftBoundary < platforms[i].leftBoundary)
				{
					double maxReachableVelocity = (platforms[i].leftBoundary - platforms[j].leftBoundary) / deltaTime;
					double minReachableVelocity = (platforms[i].leftBoundary - platforms[j].rightBoundary) / deltaTime;
					std::list<Interval>::iterator min = leftIntervals.begin(), max = leftIntervals.begin();
					bool accessiable = false;
					double speed = 0;
					while (min!=leftIntervals.end() && (*min).second < minReachableVelocity) ++min;
					while (max!=leftIntervals.end() && (*max).second < maxReachableVelocity) ++max;
					if (min != leftIntervals.end())
					{
						if (min == max)
						{
							if (maxReachableVelocity >(*min).first) {
								accessiable = true;
								if (minReachableVelocity < (*min).first)
								{
									speed = ((*min).first + maxReachableVelocity) / 2;
									(*min).first = maxReachableVelocity;
								}
								else
								{
									speed = (minReachableVelocity + maxReachableVelocity) / 2;
									double temp = (*min).first;
									(*min).first = maxReachableVelocity;
									leftIntervals.insert(min, Interval(temp, minReachableVelocity));
								}
							}
						}
						else
						{
							accessiable = true;
							if (max != leftIntervals.end() && maxReachableVelocity > (*max).first)
								(*max).first = maxReachableVelocity;
							if (minReachableVelocity <= (*min).first)
							{
								speed = ((*min).first + (*min).second) / 2;
								leftIntervals.erase(min, max);
							}
							else
							{
								speed = (minReachableVelocity + (*min).second) / 2;
								(*min).second = minReachableVelocity;
								++min;
								if (min != max)
									leftIntervals.erase(min, max);
							}

						}
					}
					if (accessiable && platforms[j].timeUsed > platforms[i].timeUsed + deltaTime)
					{
						platforms[j].timeUsed = platforms[i].timeUsed + deltaTime;
						platforms[j].prevPlatform = i;
						platforms[j].direction = 'L';
						platforms[j].velocity = speed;
					}
				}

				if (!rightIntervals.empty() && platforms[j].rightBoundary > platforms[i].rightBoundary)
				{
					double maxReachableVelocity = (platforms[j].rightBoundary - platforms[i].rightBoundary) / deltaTime;
					double minReachableVelocity = (platforms[j].leftBoundary - platforms[i].rightBoundary) / deltaTime;
					std::list<Interval>::iterator min = rightIntervals.begin(), max = rightIntervals.begin();
					bool accessiable = false;
					double speed = 0;
					while (min != rightIntervals.end() && (*min).second < minReachableVelocity) ++min;
					while (max != rightIntervals.end() && (*max).second < maxReachableVelocity) ++max;
					if (min != rightIntervals.end())
					{
						if (min == max && min != rightIntervals.end())
						{
							if (maxReachableVelocity >(*min).first) {
								accessiable = true;
								if (minReachableVelocity < (*min).first)
								{
									speed = ((*min).first + maxReachableVelocity) / 2;
									(*min).first = maxReachableVelocity;
								}
								else
								{
									speed = (minReachableVelocity + maxReachableVelocity) / 2;
									double temp = (*min).first;
									(*min).first = maxReachableVelocity;
									rightIntervals.insert(min, Interval(temp, minReachableVelocity));
								}
							}
						}
						else
						{
							accessiable = true;
							if (max != rightIntervals.end() && maxReachableVelocity > (*max).first)
								(*max).first = maxReachableVelocity;
							if (minReachableVelocity <= (*min).first)
							{
								speed = ((*min).first + (*min).second) / 2;
								rightIntervals.erase(min, max);
							}
							else
							{
								speed = (minReachableVelocity + (*min).second) / 2;
								(*min).second = minReachableVelocity;
								++min;
								rightIntervals.erase(min, max);
							}
						}
					}
					if (accessiable && platforms[j].timeUsed > platforms[i].timeUsed + deltaTime)
					{
						platforms[j].timeUsed = platforms[i].timeUsed + deltaTime;
						platforms[j].prevPlatform = i;
						platforms[j].direction = 'R';
						platforms[j].velocity = speed;
					}
				}
			}
			i++;
		}
	}

public:
	void output(std::ofstream& fout)
	{
		calculateTime();
		int i = platforms.size() - 1;
		std::cout << platforms[i].timeUsed << std::endl;
		std::list<char> dir;
		std::list<int> to;
		std::list<double> v;
		while (platforms[i].code != 0)
		{
			dir.push_front(platforms[i].direction);
			to.push_front(platforms[i].code);
			v.push_front(platforms[i].velocity);
			i = platforms[i].prevPlatform;
		}
		std::list<char>::iterator ItrC = dir.begin();
		std::list<int>::iterator ItrI = to.begin();
		std::list<double>::iterator ItrD = v.begin();
		while (ItrC != dir.end())
		{
			fout << *ItrC++ << ' ' << *ItrI++ << ' ' << std::fixed << std::setprecision(3) << *ItrD++ << std::endl;
		}
	}
};

int main()
{
	time_t start = clock();
	std::ifstream inputFile;
	inputFile.open("input22.txt", std::ios::in);
	std::ofstream outputFile;
	outputFile.open("output.txt", std::ios::out);
	if (inputFile.fail() || outputFile.fail())
	{
		std::cerr << "Cannot open the required file!" << std::endl;
	}
	while (true)
	{
		Game game(inputFile);
		game.output(outputFile);
		if (inputFile.eof())
			break;
		else
			outputFile << ';' << std::endl;
	}
	std::cout << clock() - start << std::endl;
	return 0;
}



你可能感兴趣的:(Morgan Stanley Programming Constest 2014题目Free Fall)