思路比较直接。
根据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;
}
}