题意:给出船的最大速度v,起点,终点。风在前t秒是一个方向,t秒后就一直是第二个方向。两个方向已知。
船速永远大于风速。问船在自由掌握速度和行驶方向的情况下,最快多久到终点。
分析:首先排除一种方法,那就是让船沿起点和终点的先连线线段行进,用一定的船的分速度抵消风速在行驶垂直方向的分速度。
不能这么做的原因如下,暂时我们把终点方向称作前方,而风与前方垂直的方向称为左或者右。第一个风向可能向左吹,第二个风可能向右吹,这样不需要用船速度去实时抵消风速。
即使开始被吹偏了,后来还是能被吹回来。
真正的做法是二分查找总时间。时间足够长则一定可以到达,不够长则一定不能到达。
不要担心时间太长风会把船吹得太远,因为船速是大于风速的,短时间能到达,长时间更能到达。
对于一个给定的总时间a,我们把船的位移分为三个向量之和,分别是风一和风二和船, 三者的位移。
前两个很好计算,因为方向是固定的。而第三个我们认为它是在从前两个向量之和的位置沿直线向终点前进,这是最佳策略。
我们现在只需要看船能否在a时间内走完两相量和到终点的连线。
这一题的二分查找同样使用了限制循环次数的方式来防止超时。
自由掌握方向的这种运动题,很可能需要拆分速度和位移。
#include <cstdio> #include <cmath> #include <algorithm> using namespace std; #define d(x) x #define zero(x) (((x)>0?(x):-(x))<eps) #define eps 1.0E-8 #define MAX_POINT_NUM 0 int double_cmp(double a) { if (zero(a)) return 0; return a > 0 ? 1 : -1; } struct Point { double x,y; Point() {} Point(double x, double y):x(x), y(y) {} Point operator - (Point &a) { return Point(x - a.x, y - a.y); } bool operator <(const Point &a)const { return atan2(y, x) < atan2(a.y, a.x); } bool operator == (const Point &a) const { return x == a.x && y == a.y; } }; double point_dist(Point a) { return sqrt(a.x * a.x + a.y * a.y); } double point_dist(Point a, Point b) { return point_dist(a - b); } double dot_product(Point a, Point b) { return a.x * b.x + a.y * b.y; } double dot_product(Point p0, Point p1, Point p2) { return dot_product(p1 - p0, p2 - p0); } Point s, e; Point wind1; Point wind2; double v, t; void input() { int x, y; scanf("%d%d", &x, &y); s = Point(x, y); scanf("%d%d", &x, &y); e = Point(x, y) - s; s = Point(0, 0); scanf("%lf%lf", &v, &t); scanf("%d%d", &x, &y); wind1 = Point(x, y); scanf("%d%d", &x, &y); wind2 = Point(x, y); } bool ok(double a) { double t1 = min(a, t); double t2 = max(a - t, 0.0); Point by_wind = Point(t1 * wind1.x + t2 * wind2.x, t1 * wind1.y + t2 * wind2.y); double dist = point_dist(by_wind - e); return double_cmp(dist - v * a) <= 0; } double binary_search(double l, double r) { for (int i = 0; i < 400; i++) { if (double_cmp(l - r) == 0) break; double mid = (l + r) / 2; if (ok(mid)) { r = mid; }else { l = mid; } } return l; } int main() { input(); printf("%.18f\n", binary_search(0, 1e9)); return 0; }