1. 程式人生 > >HDU-2297 Run 計算幾何 凸包思想

HDU-2297 Run 計算幾何 凸包思想

HDU-2297 Run

題意: 一維線段n個可以運動的點,位置為p, 速度為v。 求在運動的過程中有多少點可以領跑(在最前面)。
分析: 可以將速度v也變成一個維度, 一個點要超過另一個點的前提條件是速度更大, 其中可以根據求凸包的思想, 如果這個點到另一個點的相對距離與相對速度做除法運算, 即求得斜率。 斜率大的可以更先跑到前面並且不會被他超過, 在這裡要對位置和速度排序, 然後按照求凸包的思想直接求解。 關於一個點可以在超過最前面的點超過另一個點解釋見下圖。綠色和藍色分別代表斜率。
在這裡插入圖片描述
程式碼:

#include <bits/stdc++.h>

using
namespace std; const double eps = 1e-8; int sgn(double x) { if (fabs(x) < eps) return 0; else if (x < 0) return -1; else return 1; } struct Point { double p, v; Point() {} Point(double _p, double _v) { p = _p; v = _v; } bool
operator<(const Point b) const { if (sgn(p - b.p) == 0) return sgn(v - b.v) < 0; else return sgn(p - b.p) > 0; } }; const int MAXN = 1e5 + 10; Point p[MAXN], st[MAXN]; int n; bool check(Point p0, Point a, Point b) { double area = (b.p - a.p) *
(p0.v - a.v) - (a.p - p0.p) * (a.v - b.v); return sgn(area) >= 0; } int solve() { int top = 1; sort(p, p + n); double mv = p[0].v; st[0] = Point(p[0].p, 0); st[1] = p[0]; //st[top++] = p[0]; for (int i = 1; i < n; i++) { if (p[i].v < mv) continue; while (top > 0 && check(p[i], st[top], st[top - 1])) top--; st[++top] = p[i]; mv = p[i].v; } return top; } int main() { int T; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%lf%lf", &p[i].p, &p[i].v); printf("%d\n", solve()); } return 0; }