題意:給出船的最大速度v,起點,終點。風在前t秒是一個方向,t秒後就一直是第二個方向。兩個方向已知。ide
船速永遠大於風速。問船在自由掌握速度和行駛方向的狀況下,最快多久到終點。spa
分析:首先排除一種方法,那就是讓船沿起點和終點的先連線線段行進,用必定的船的分速度抵消風速在行駛垂直方向的分速度。code
不能這麼作的緣由以下,暫時咱們把終點方向稱做前方,而風與前方垂直的方向稱爲左或者右。第一個風向可能向左吹,第二個風可能向右吹,這樣不須要用船速度去實時抵消風速。blog
即便開始被吹偏了,後來仍是能被吹回來。input
真正的作法是二分查找總時間。時間足夠長則必定能夠到達,不夠長則必定不能到達。it
不要擔憂時間太長風會把船吹得太遠,由於船速是大於風速的,短期能到達,長時間更能到達。io
對於一個給定的總時間a,咱們把船的位移分爲三個向量之和,分別是風一和風二和船, 三者的位移。event
前兩個很好計算,由於方向是固定的。而第三個咱們認爲它是在從前兩個向量之和的位置沿直線向終點前進,這是最佳策略。class
咱們如今只須要看船可否在a時間內走完兩相量和到終點的連線。cli
這一題的二分查找一樣使用了限制循環次數的方式來防止超時。
自由掌握方向的這種運動題,極可能須要拆分速度和位移。
#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; }