POJ 2074 /// 判斷直線與線段相交 視野盲區
阿新 • • 發佈:2018-09-14
相交 接下來 cst 位置 aps printf discus alt else
題目大意:
將所有物體抽象成一段橫向的線段
給定房子的位置和人行道的位置
接下來給定n個障礙物的位置
位置信息為(x1,x2,y) 即x1-x2的線段 y相同因為是橫向的
求最長的能看到整個房子的一段人行道的長度
若不在 y(房子)和y(人行道)之間的 不會有視野的阻礙
註意邊界處理 因為盲區可能包含在人行道內 也可能超出
#include <cstdio> #include <algorithm> #include <cmath> using namespace std; const double eps=1e-10; double add(doubleView Codea,double b) { if(abs(a+b)<eps*(abs(a)+abs(b))) return 0; return a+b; } struct P { double x,y; P(){}; P(double _x,double _y):x(_x),y(_y){}; P operator - (P p) { return P(add(x,-p.x),add(y,-p.y)); } P operator + (P p) { return P(add(x,p.x),add(y,p.y)); } Poperator * (double d) { return P(x*d,y*d); } double dot(P p) { return add(x*p.x,y*p.y); } double det(P p) { return add(x*p.y,-y*p.x); } }; struct Line{ P s,e; Line(){}; Line(P _s,P _e):s(_s),e(_e){}; }H, L, p[105]; bool cmp(Line a,Line b) { if(a.s.x==b.s.x) returna.e.x<b.e.x; return a.s.x<b.s.x; } // 求直線ab與直線cd的交點 P ins(P a,P b,P c,P d) { return a+(b-a)*((d-c).det(c-a)/(d-c).det(b-a)); } // 判斷c點是否在線段ab上 bool onSeg(P a,P b,P c) { return (a-c).det(b-c)==0 && (a-c).dot(b-c)<=0; } int main() { double a,b,c; while(~scanf("%lf%lf%lf",&a,&b,&c)) { if(a==0 && b==0 && c==0) break; H.s.x=a, H.e.x=b, H.s.y=H.e.y=c; // 房子 scanf("%lf%lf%lf",&a,&b,&c); L.s.x=a, L.e.x=b, L.s.y=L.e.y=c; // 人行道 int n,cnt=0; scanf("%d",&n); double up=max(H.s.y,L.s.y); double dw=min(H.s.y,L.s.y); for(int i=0;i<n;i++) { scanf("%lf%lf%lf",&a,&b,&c); if(c>=up || c<=dw) continue; // 不在房子和人行道之間的範圍 不會有影響 p[cnt].s.x=a, p[cnt].e.x=b; p[cnt].s.y=p[cnt].e.y=c; cnt++; } sort(p,p+cnt,cmp); double lastX=L.s.x, ans=0; for(int i=0;i<cnt;i++) { P x1=ins(H.e,p[i].s,L.s,L.e); // 房子右端連障礙左端 與 人行道 的交點 P y1=ins(H.s,p[i].e,L.s,L.e); // 房子左端連障礙右端 與 人行道 的交點 if(onSeg(L.s,L.e,x1)) ans=max(ans,x1.x-lastX); // 盲區為x1-y1 若這段盲區的起點在人行道上 // 那麽盲區左端之前存在一段 更新答案 lastX=max(lastX,y1.x); // 下一段的開端是位於盲區的右端 } if(lastX<L.e.x) ans=max(ans,L.e.x-lastX); // 最後一段盲區位於人行道內 那麽盲區之後還有一段 if(ans) printf("%.2f\n",ans); else printf("No View\n"); } return 0; } /*discuss裏的大神們提供的經典測試數據 2 6 6 0 15 0 3 1 2 1 3 4 1 12 13 1 1 5 5 0 10 0 1 0 15 1 2 6 6 0 15 0 3 1 2 1 3 4 1 12 13 1 2 6 6 0 15 0 4 1 2 1 3 4 1 12 13 1 1 5 2 2 6 6 0 15 0 2 0 5 3 6 15 3 2 6 6 0 15 0 2 6 10 1 0 2 1 2 6 6 0 15 0 1 2 6 7 2 6 6 0 15 0 1 4 4.5 5.5 2 6 6 0 15 0 16 0 1 3 1.5 2 3 2.5 3 3 3.5 4 3 4.5 5 3 5.5 6 3 6.5 7 3 7.5 8 3 8.5 9 3 9.5 10 3 10.5 11 3 11.5 12 3 12.5 13 3 13.5 14 3 14.5 15 3 15.5 16 3 2 6 6 0 15 0 16 0 1 .1 1.5 2 .1 2.5 3 .1 3.5 4 .1 4.5 5 .1 5.5 6 .1 6.5 7 .1 7.5 8 .1 8.5 9 .1 9.5 10 .1 10.5 11 .1 11.5 12 .1 12.5 13 .1 13.5 14 .1 14.5 15 .1 15.5 16 .1 2 6 6 0 15 0 14 0 1 3 1.5 2 3 2.5 3 3 3.5 4 3 4.5 5 3 5.5 6 3 8.5 9 3 9.5 10 3 10.5 11 3 11.5 12 3 12.5 13 3 13.5 14 3 14.5 15 3 15.5 16 3 2 6 6 0 4000000000 0 2 1 2 1 15 16 3 2 6 6 0 15 1 5 1 1.5 6 17 18 1 3 5 3 0 20 10 0 20 0.5 *//* 答案: 8.80 No View 8.80 6.70 No View 4.00 15.00 No View No View 0.44 1.00 3999999970.00 8.00 */
POJ 2074 /// 判斷直線與線段相交 視野盲區