題目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=16454ios
1.對於每一顆流星而言,真正有意義的是它穿越矩形的有效時間,因此其實咱們須要獲得全部流星的有效時間this
2.這樣的話,原問題就轉化更加具體的:某個時刻最多同時穿過多少個時間段?spa
解決方案:code
將每個時間區間,轉化爲兩個事件:開始事件和結束事件。咱們對全部事件按照時間排序,而後咱們有一個初始化爲0的tot變量計數,接着遍歷這個序列,遇到開始事件就+1,遇到結束時間就-1,而後在遍歷的過程當中保存最大的tot,這個最大值就是最後的解。blog
最後要注意開始時間與結束事件重疊的狀況,即當某個時刻開始時間與結束事件重疊。若是是先+後-的話,那麼最大值會是2,相反就會使1。顯然,在這裏,後者纔是正確的,由於由題意全部時間區間結尾開區間。排序
#include <cstdio> #include <iostream> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; struct P { double t; int type; P(double t=0, int type=0) { this->t = t; this->type = type; } bool operator<(const P& p) const { if(t == p.t) return type > p.type; // 時間同樣時,優先結束事件 return t < p.t; } } p[200005]; int tot; double l, r; // 獲得某顆流星在某一維度上面通過矩形範圍的區間,若是 左邊界>右邊界 說明 區間不存在 void f(int x, int w, int a) { if(a == 0) { if(x <= 0 || x >= w) { l = INF; r = 0; } } else if(a > 0){ l = max(l, -1.0*x/a); r = min(r, 1.0*(w-x)/a); } else { l = max(l, 1.0*(w-x)/a); r = min(r, -1.0*x/a); } } int main () { int T, w, h, n; scanf("%d", &T); while(T--) { scanf("%d%d%d", &w, &h, &n); int x, y, a, b; tot = 0; for(int i=0; i<n; i++) { scanf("%d%d%d%d", &x, &y, &a, &b); l = 0, r = INF; f(x, w, a); f(y, h, b); if(l<r) { p[tot++] = P(l, 0); p[tot++] = P(r, 1); } } sort(p, p+tot); int cur = 0, ans = 0; for(int i=0; i<tot; i++) { if(p[i].type == 0) { // 開始事件 +1 cur++; if(cur > ans) ans = cur; } else cur--; // 結束事件 -1 } printf("%d\n", ans); } return 0; }