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;
}

 

posted @ 2017-12-19 20:31  luyouqi233  阅读(301)  评论(0编辑  收藏  举报