题目原文已经找不到了,大体的内容如下:
以地面为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; }