POJ 2074 直线相交

思路比较直接。
根据house的位置与每一个obstruction之间的相对位置,求出在line上不能够看到的区域Area的位置。
对所有的位置进行线性扫描,找出最长的通视距离,这个扫描过程需要细致。
最后还有几个致命的trick,自己动手吧,WA看dicuss中的测试数据.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>

using namespace std;
const double eps=1e-8;
const int maxn=1000+10;
double ans;
int sgn(double x)
{
    if(fabs(x)<eps)
        return 0;
    if(x>0)
        return 1;
    if(x<0)
        return -1;
}
double Max(double x,double y)
{   
    return sgn(x-y)>0 ? x : y;
}
double Min(double x,double y)
{
    return sgn(x-y)<0 ? x : y;
}

struct point
{
    double x,y;
    point() {}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
};
typedef point vector;
vector operator + (vector A,vector B)
{
    return point(A.x+B.x,A.y+B.y);
}
vector operator - (point A,point B)
{
    return point(A.x-B.x,A.y-B.y);
}
double operator ^ (vector A,vector B)
{
    return A.x*B.y-A.y*B.x;
}
double operator * (vector A,vector B)
{
    return A.x*B.x+A.y*B.y;
}
struct line
{
    point s,e;
    line() {}
    line(point _s,point _e)
    {
        s=_s;
        e=_e;
    }
};

struct Area
{
    double l,r;
};

line house; //房屋
line pro; //界址线
line obs[maxn]; //障碍物 
double divide[2*maxn];
bool flag;
Area area[maxn];
int n;//障碍的数目 
int cmp(Area x,Area y)
{
    return x.l<y.l;
}

double crosspoint(line l1,line l2) //直线相交求交点,返回横坐标x的值 
{
    double a1=(l1.e-l1.s)^(l2.s-l1.s);
    double a2=(l1.e-l1.s)^(l2.e-l1.s);
    return (l2.s.x*a2-l2.e.x*a1)/(a2-a1);
} 

void solve() 
{
    int cnt=0; 
    for(int i=0;i<n;i++)
    {
        line lview,rview;
        lview=line(house.e,obs[i].s);
        rview=line(house.s,obs[i].e);
        if(sgn(crosspoint(lview,pro)-pro.e.x)>0 || sgn(crosspoint(rview,pro)-pro.s.x)<0) 
            continue;
        area[cnt].l=Max(crosspoint(lview,pro),pro.s.x);
        area[cnt].r=Min(crosspoint(rview,pro),pro.e.x);
        cnt++;
    }
    sort(area,area+n,cmp);
    /*for(int i=0;i<cnt;i++)
        printf("(%.2lf,%.2lf)\n",area[i].l,area[i].r);*/
    double max=0;
    double last=pro.s.x;
    if(cnt!=0)
    {
        for(int i=0;i<n;i++)
        {
            if(sgn(area[i].l-last)>0)  
            {  
                max= Max(max,area[i].l-last);  
                last=area[i].r;  
            }  
            else if(sgn(area[i].r-last) > 0)  
                last=area[i].r;  
        }  
        if(sgn(last-pro.e.x)< 0)  
            max=Max(max, pro.e.x-last); 
    }
    else 
        max=pro.e.x-pro.s.x;
    if(sgn(max)==0)
        flag=false;
    else
        ans=max;
}

int main()
{
    //freopen("test.txt","r",stdin);
    double x1,x2,y1;
    while(~scanf("%lf%lf%lf",&x1,&x2,&y1))
    {
        flag=true;
        memset(area,0,sizeof(area));
        memset(obs,0,sizeof(obs));
        if(x1==0 && x2==0 && y1==0)
            break;
        house.s=point(x1,y1);
        house.e=point(x2,y1);
        double a,b,c;
        scanf("%lf%lf%lf",&a,&b,&c);
        pro.s=point(a,c);
        pro.e=point(b,c);
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf%lf",&a,&b,&c);
            if(sgn(house.s.y-c)<0 || sgn(house.s.y-pro.s.y)<0 || sgn(c-pro.s.y)<0)
                continue;
            obs[i].s=point(a,c);
            obs[i].e=point(b,c);
        }
        solve();
        if(flag)
            printf("%.2lf\n",ans);
        else
            cout<<"No View"<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值