题意:从一条线段(property)上观察另一与之平行的线段(house),其中有很多与它们都平行的线段(障碍物),求在property得可见整条线段house的最长连续范围的长度。
初时的想法是,求出在哪些点的范围可以看到整个HOUSE。 后来在DIS上找了几组数据,就变得都要特判了。再想想,既然找可行点不行,就找不可行的点,就是在哪些点的范围不能看到整个HOUSE。这样,代码就简化了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n;
const double eps=0.00000001;
struct point{
double x,y;
}st,en;
struct line{
point start,end;
}obst[200],house,pl;
struct xcor{
double p;
int flag;
xcor(){ flag=0;}
}xx[1200];
int xxc; double tmp;
void slove(point s, point t){
if(s.x==t.x){
tmp=t.x;
}
else{
double k=(s.y-t.y)/(s.x-t.x);
tmp=(pl.start.y-s.y)/k+s.x;
}
if(tmp>pl.end.x) tmp=pl.end.x;
if(tmp<pl.start.x) tmp=pl.start.x;
}
bool cmp(xcor A,xcor B){
if(A.p<B.p)return true;
else if(A.p==B.p){
if(A.flag<B.flag)return true;
}
return false;
}
int main(){
double a,b,c;
while(cin>>a>>b>>c){
if(a==0&&b==0&&c==0) break;
xxc=0;
st.x=a; st.y=c; en.x=b; en.y=c;
house.start=st; house.end=en;
cin>>a>>b>>c;
st.x=a; st.y=c; en.x=b; en.y=c;
pl.start=st; pl.end=en;
cin>>n;
int co=0;
for(int i=0;i<n;i++){
cin>>a>>b>>c;
if(c<house.start.y&&c>pl.start.y){
st.x=a; st.y=c; en.x=b; en.y=c;
obst[co].start=st; obst[co].end=en;
co++;
}
}
n=co;
for(int i=0;i<n;i++){
slove(house.end,obst[i].start);
xx[xxc].p=tmp; xx[xxc].flag=-1;
xxc++;
slove(house.start,obst[i].end);
xx[xxc].p=tmp; xx[xxc].flag=1;
xxc++;
}
sort(xx,xx+xxc,cmp);
int now=0; double pre,lo,tt;
pre=pl.start.x; lo=0;
for(int i=0;i<xxc;i++){
if(now==0){
tt=xx[i].p-pre;
if(tt>lo) lo=tt;
}
now+=xx[i].flag;
pre=xx[i].p;
}
tt=pl.end.x-pre;
if(tt>lo) lo=tt;
if(lo>0)
printf("%0.2lf\n",lo);
else printf("No View\n");
}
}