To satisfy the architect's need to know how visible the house is, you must write a program that accepts as input the locations of the house, property line, and surrounding obstructions and calculates the longest continuous portion of the property line from which the entire house can be seen, with no part blocked by any obstruction.
< x1 > < x2 > < y >
Where x1, x2, and y are non-negative real numbers. x1 < x2
An input file can describe the architecture and landscape of multiple houses. For each house, the first line will have the coordinates of the house. The second line will contain the coordinates of the property line. The third line will have a single integer that represents the number of obstructions, and the following lines will have the coordinates of the obstructions, one per line.
Following the final house, a line "0 0 0" will end the file.
For each house, the house will be above the property line (house y > property line y). No obstruction will overlap with the house or property line, e.g. if obstacle y = house y, you are guaranteed the entire range obstacle[x1, x2] does not intersect with house[x1, x2].
For each house, your program should print a line containing the length of the longest continuous segment of the property line from which the entire house can be to a precision of 2 decimal places. If there is no section of the property line where the entire house can be seen, print "No View".
这里有一个物理知识点。我们站在C处看A,在A和C之间如果存在障碍物B。 那么视觉盲点就A的左端点与B的右端点构成的直线在C上形成一个交点。同样,A的右端点与B的左端点构成的直线在C上形成一个交点。两个交点之间的就是视觉盲点。
我们枚举所有的障碍物,求得所有的视觉盲点的直线。之后按左端点排序。从规定的马路区间内找最大的间隔即可。
核心代码
//通过一条直线的两个点,计算在某一个y坐标时的坐标
point pointGetFromLine(line &l,double y){
if( isZero(l.a.y - l.b.y) ){
if(isZero(l.a.y - y))
return point(0.0,y);
return point(0.0,0.0);
}else if(isZero(l.a.x - l.b.x)){
return point(l.a.x,y);
}else{
double ret = l.a.x - (l.a.y - y)*(l.b.x-l.a.x)/(l.b.y - l.a.y);
return point(ret,y);
}
}
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int MAXN = 1111;
double hx1,hx2,hy; // house
double fx1,fx2,hf; // property line
int n;
bool isZero(double a){
if(fabs(a) < eps)
return true;
else return false;
}
struct point
{
double x,y;
point(){}
point(double _x,double _y){ x=_x,y=_y;}
};
struct line
{
point a,b;
line(){}
line(point _a,point _b){a = _a,b=_b;}
}L[MAXN];
//通过一条直线的两个点,计算在某一个y坐标时的坐标
point pointGetFromLine(line &l,double y){
if( isZero(l.a.y - l.b.y) ){
if(isZero(l.a.y - y))
return point(0.0,y);
return point(0.0,0.0);
}else if(isZero(l.a.x - l.b.x)){
return point(l.a.x,y);
}else{
double ret = l.a.x - (l.a.y - y)*(l.b.x-l.a.x)/(l.b.y - l.a.y);
return point(ret,y);
}
}
struct inFireLine{
point p1;
point p2;
inFireLine(){}
inFireLine(point _p1,point _p2){
p1=_p1; p2=_p2;
}
}inFire[MAXN<<1];
//bool cmp(int i,int j){
// return inFire[i].p.x < inFire[j].p.x || ( inFire[i].p.x == inFire[j].p.x && !is_right);
//}
bool cmp(const inFireLine &f1, const inFireLine &f2){
return f1.p1.x < f2.p1.x || ( f1.p1.x == f2.p1.x && f1.p2.x < f2.p2.x);
}
int firCur;
void solve(){
point p_house_left = point(hx1,hy),p_house_right = point(hx2,hy);
firCur = 0;
for(int i = 0;i < n;i++){
if(L[i].a.y + eps > hy || L[i].a.y + eps < hf || isZero(hy - L[i].a.y) || isZero(hf - L[i].a.y) ) //不在中间的障碍物直接抛弃
continue;
//房子的右点 跟遮挡物的左点 ,y
line l1 = line(p_house_right,L[i].a);
point t1 = pointGetFromLine( l1, hf);
t1.x = max(1.0*fx1,t1.x);
line l2 = line(p_house_left,L[i].b);
//房子的左点 跟遮挡物的左点 ,y
point t2 = pointGetFromLine( l2, hf);
t2.x = min(1.0*fx2,t2.x);
if(t1.x > fx2 + eps || t2.x +eps < fx1)
continue;
inFire[firCur++] = inFireLine(t1,t2);
}
sort(inFire,inFire+firCur,cmp);
double ans = 0;
double lastX = fx1,left_tot = 0; //left_tot是计算左节点的数目
if(firCur){
for(int i = 0;i < firCur;i++){
if(inFire[i].p1.x > lastX + eps){
ans = max(ans, inFire[i].p1.x - lastX);
lastX = inFire[i].p2.x;
}else if(inFire[i].p2.x > lastX + eps){
lastX = inFire[i].p2.x;
}
}
if(lastX + eps < fx2)
ans = max(ans,fx2 - lastX);
}else{
ans = fx2-fx1;
}
if(isZero(ans)){
printf("0.00\n");
}else{
printf("%.2lf\n",ans);
}
}
int main(){
while(cin >> hx1 >> hx2 >> hy){
if(isZero(hx1+hx2+hy))
break;
cin >> fx1 >> fx2 >> hf;
cin >> n;
double a,b,c;
for(int i = 0;i < n;i++){
cin >> a >> b >> c;
L[i].a = point(a,c); L[i].b = point(b,c);
}
solve();
}
return 0;
}