POJ2074:Line of Sight——题解
http://poj.org/problem?id=2074
题目大意:(下面的线段都与x轴平行)给两条线段,一个点在其中一条线段看另一条线段,但是中间有很多线段阻挡视线。求在线段上最大连续区间使得在上面的点都能看见另一条线段。
——————————————
这题的思路很简单,首先根据左端点先排个序,然后找前一条线段的右端点和房子左端点连,后一条线段的左端点和房子右端点连,那么两条连线与路的交的范围即是可行解。
但是debug真的累……好在poj有神犇提供了部分debug数据,经过多次尝试,发现:
1.筛除不在路和房子之间的线段。
2.可行解区域可能超过路。
3.线段可能互相遮挡。
第三条蛮麻烦的,一个简单粗暴的比较方法就是枚举所有线段,判断是否有和线段相交,如果相交则更换为该线段的左/右端点。
#include<cstdio> #include<queue> #include<cctype> #include<cstring> #include<vector> #include<cmath> #include<algorithm> using namespace std; typedef double dl; const int INF=2147483647; const int N=201; struct point{//既是向量又是点 dl x; dl y; }; struct line{ dl x1; dl x2; dl y; }p[N],st,ed; bool cmp(line a,line b){ return (a.x1<b.x1||(a.x1==b.x1&&a.x2<b.x2)||(a.x1==b.x1&&a.x2==b.x2&&a.y<b.y)); } inline point getmag(point a,point b){ point s; s.x=b.x-a.x;s.y=b.y-a.y; return s; } inline int multiX(point a,point b){ return a.x*b.y-b.x*a.y; } inline bool check(point a,point b,point c,point d){ dl d1=multiX(getmag(c,d),getmag(c,a))*multiX(getmag(c,d),getmag(c,b)); dl d2=multiX(getmag(a,b),getmag(a,c))*multiX(getmag(a,b),getmag(a,d)); if(d1<=0&&d2<=0)return 1; return 0; } inline point intersection(point a,point b,point c,point d){ point s; dl a1=a.y-b.y,b1=b.x-a.x,c1=a.x*b.y-b.x*a.y; dl a2=c.y-d.y,b2=d.x-c.x,c2=c.x*d.y-d.x*c.y; s.x=(c1*b2-c2*b1)/(a2*b1-a1*b2); s.y=(a2*c1-a1*c2)/(a1*b2-a2*b1); return s; } int n; int main(){ while(scanf("%lf%lf%lf",&st.x1,&st.x2,&st.y)!=EOF&&st.x1+st.x2+st.y!=0){ scanf("%lf%lf%lf",&ed.x1,&ed.x2,&ed.y); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lf%lf%lf",&p[i].x1,&p[i].x2,&p[i].y); sort(p+1,p+n+1,cmp); double maxn=0,l=0,r=0; bool f=0; for(int i=n;i>=1;i--){ if(p[i].y>st.y||p[i].y<ed.y)continue; n=i; break; } for(int i=1;i<=n+1;i++){ if(p[i].y>st.y||p[i].y<ed.y)continue; if(!f){ l=ed.x1; f=1; } else{ point a,b,c,d; a.x=ed.x1;a.y=ed.y; b.x=ed.x2;b.y=ed.y; c.x=st.x1;c.y=st.y; d.x=p[i-1].x2;d.y=p[i-1].y; for(int j=1;j<=n;j++){ if(p[j].y>st.y||p[j].y<ed.y)continue; if(i-1==j)continue; point e,f; e.x=p[j].x1;e.y=p[j].y; f.x=p[j].x2;f.y=p[j].y; if(check(c,d,e,f)){ d=f; } } l=intersection(a,b,c,d).x; } if(i==n+1)r=ed.x2; else{ point a,b,c,d; a.x=ed.x1;a.y=ed.y; b.x=ed.x2;b.y=ed.y; c.x=st.x2;c.y=st.y; d.x=p[i].x1;d.y=p[i].y; for(int j=1;j<=n;j++){ if(p[j].y>st.y||p[j].y<ed.y)continue; if(i-1==j)continue; point e,f; e.x=p[j].x1;e.y=p[j].y; f.x=p[j].x2;f.y=p[j].y; if(check(c,d,e,f)){ d=e; } } r=intersection(a,b,c,d).x; } if(l<r){ if(l<ed.x1)l=ed.x1; if(r>ed.x2)r=ed.x2; maxn=max(maxn,r-l); } } if(maxn==0){ puts("No View"); }else{ printf("%.2f\n",maxn); } } return 0; }