題意:二維平面上有一條直線,直線上放置了一個激光發射器,會嚮導軌兩側沿導軌垂直方向發射寬度爲 L 的激光束。平面上還有 n 條線段,而且線段和線段、線段和直線之間都沒有公共點,線段和直線的夾角不超過 85◦,激光束不能穿透線段,你須要求出激光束能照射到的線段長度之和的最大值。
作法:先進行座標變換,將給定直線移到x軸上,注意首先將直線的一端移到原點,而後再旋轉。(樣例數據全都從原點出發。。。沒發現。就gg了十幾發,好腦殘啊。。)考慮將每一個線段投影到直線上,這些點將直線分紅一些線段,對於每一段,找到它上方最近的那個線段,而後計算單位長度的貢獻,最後的答案就能夠雙指針求出了。對於查詢上方最近的線段,使用set維護掃描線便可。雙指針還寫崩了。。。這題出出來就gg了啊。。。碼力弱炸,還手殘。c++
#include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) #define pb push_back typedef long double db; const db EPS = 0; const db INF = 1e100; inline int sgn(db x, db E = EPS){return x<-E?-1:x>E;} inline int cmp(db a,db b,db E = EPS){return sgn(a-b, E);} struct P{ db x,y; bool operator<(P o) const { return cmp(x,o.x) != 0? cmp(x,o.x) == -1 : cmp(y,o.y) == -1; } bool operator>(P o) const { return cmp(x,o.x) != 0? cmp(x,o.x) == 1 : cmp(y,o.y) == 1; } bool operator==(P o) { return cmp(x,o.x) == 0 && cmp(y,o.y) == 0; } void read(){ int _x,_y; scanf("%d%d",&_x,&_y); x=_x,y=_y; } P operator + (P o) { return {x+o.x,y+o.y}; } P operator - (P o) { return {x-o.x,y-o.y}; } db det(P o) { return x*o.y-y*o.x; } db dot(P o){ return x*o.x+y*o.y; } db disTo(P p) { return (*this - p).abs(); } db alpha() { return atan2(y, x); } db abs() { return sqrt(abs2());} db abs2() { return x * x + y * y; } P rot(db a) { db c = cos(a), s = sin(a); return {c*x-s*y, s*x+c*y}; } }; struct L { P ps[2]; L(){} L(P p1, P p2) { ps[0] = p1, ps[1] = p2; } P& operator[](int i) { return ps[i]; } P dir() { return ps[1] - ps[0]; } bool include(P p) { return sgn((ps[1]-ps[0]).det(p-ps[0])); } }; db nowx = 0; int top[100010]; vector<db> scan; int sc; struct seg { P u, v; int id; db k; seg(){} seg(P _u, P _v, int _id) { id = _id; u = _u; v = _v; k = (v.y - u.y) / (v.x - u.x); } bool operator < (const seg a) const { db v1 = u.y + k * (nowx - u.x); db v2 = a.u.y + a.k * (nowx - a.u.x); if( cmp(v1, v2) == 0 ) return k < a.k; return v1 < v2; } }; set< seg > S; set< seg >::iterator it[100010]; struct Q { P e; int id; bool operator < (Q a) { if(e == a.e) return id < a.id; return e < a.e; } }; vector< Q > qs; vector<db> cal(vector<L> ls) { int n = ls.size(); qs.clear(); rep(i,0,n-1) { if(ls[i][0].x > ls[i][1].x) swap(ls[i][0], ls[i][1]); qs.pb({ls[i][0], -i-1}); qs.pb({ls[i][1], i+1}); } sort(qs.begin(),qs.end()); nowx = 0; S.clear(); rep(i,0,sc-1) top[i] = -1; for(int j = 0, i = 0; i < sc; ++ i) { nowx = scan[i]; for( ; j < qs.size() && qs[j].e.x <= nowx ; ++j) { if(qs[j].id < 0) { int ID = (-qs[j].id)-1; it[ID] = S.insert(seg(ls[ID][0],ls[ID][1],ID)).first; } else { int ID = qs[j].id-1; S.erase(it[ID]); } } if(!S.empty()) top[i] = (*S.begin()).id; } function<db(int)> cost = [&](int tp) -> db { return abs( ls[tp][0].disTo(ls[tp][1]) / (ls[tp][1].x - ls[tp][0].x) ); }; vector<db> V; rep(i, 0, sc-2) { if(top[i] != -1) V.pb(cost(top[i])); else V.pb(0); } return V; } db pv[100010], pc[100010]; db cala(vector< pair<db,db> > &V, db Len) { function<db(db,int,int)> MX = [&](db LL, int p1, int p2) -> db { db tmp = 0; if(0 <= p1 && p1 <= sc-2) tmp = max(tmp, V[p1].second * min(LL, V[p1].first) ); if(0 <= p2 && p2 <= sc-2) tmp = max(tmp, V[p2].second * min(LL, V[p2].first) ); return tmp; }; db ans = 0; int p1 = 0, p2 = 0; db tC = 0, tL = 0; do { if(Len >= tL) ans = max(ans, tC + MX(Len-tL, p1-1, p2 ) ); if(p2 < sc-1 && cmp(tL + V[p2].first, Len) <= 0) { tL += V[p2].first; tC += V[p2].first * V[p2].second; ++ p2; } else if(p1 <= p2) { tL -= V[p1].first; tC -= V[p1].first * V[p1].second; ++ p1; } else { if(p2 < sc-1) { tL += V[p2].first; tC += V[p2].first * V[p2].second; ++ p2; } if(p1 <= p2) { tL -= V[p1].first; tC -= V[p1].first * V[p1].second; ++ p1; } } if(Len >= tL) ans = max(ans, tC + MX(Len-tL, p1-1, p2 ) ); } while(p1 < sc-1 || p2 < sc-1); return ans; } int n; L line[100010]; P p1, p2; db Len; vector<L> UP, LW; void init() { UP.clear(); LW.clear(); if(p1 > p2) swap(p1, p2); db a = -(p2-p1).alpha(); rep(i,0,n-1) { line[i][0] = (line[i][0]-p1).rot(a); line[i][1] = (line[i][1]-p1).rot(a); if( sgn(line[i][0].y) == 1 ) UP.pb(line[i]); else LW.pb( L( {line[i][0].x, -line[i][0].y} , {line[i][1].x, -line[i][1].y} ) ); } scan.clear(); rep(i,0,(int)UP.size()-1) { scan.pb(UP[i][0].x), scan.pb(UP[i][1].x); } rep(i,0,(int)LW.size()-1) { scan.pb(LW[i][0].x), scan.pb(LW[i][1].x); } sort(scan.begin(),scan.end()); scan.erase( unique(scan.begin(),scan.end()), scan.end()); sc = scan.size(); } int main() { int _; scanf("%d",&_); while(_--) { scanf("%d",&n); rep(i,0,n-1) { line[i][0].read(); line[i][1].read(); } p1.read(), p2.read(); int t; scanf("%d",&t), Len = t; init(); vector<db> V1 = cal(UP); vector<db> V2 = cal(LW); vector<pair<db,db>> V; rep(i, 0, (int)V1.size()-1) { V.pb({scan[i+1]-scan[i], V1[i] + V2[i]}); } db ans = cala(V, Len); printf("%.12Lf\n",ans); } return 0; }