F - Line of Sight POJ - 2074(简单计算几何)

F - Line of Sight

 POJ - 2074 

An architect is very proud of his new home and wants to be sure it can be seen by people passing by his property line along the street. The property contains various trees, shrubs, hedges, and other obstructions that may block the view. For the purpose of this problem, model the house, property line, and obstructions as straight lines parallel to the x axis: 


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.

Input

Because each object is a line, it is represented in the input file with a left and right x coordinate followed by a single y coordinate: 
< 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].

Output

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".

Sample Input

2 6 6
0 15 0
3
1 2 1
3 4 1
12 13 1
1 5 5
0 10 0
1
0 15 1
0 0 0

Sample Output

8.80
No View

题意:求在公路上看到房子,求能看到房子的最大连续的公路长度是多少?

思路:反过来想,先求不能看到房子的公路盲区,即求房子左端点与障碍物右端点作直线,该直线与公路的交点作为该障碍物造成的盲区的右端点,房子右端点与障碍物左端点作直线,该直线与公路的交点作为该障碍物造成的盲区的左端点,然后对盲区按左端点从小到大的顺序排序,最后取所有当前盲区的最左端点与前面盲区延伸到最有右端的差值(连续非盲区)的最大值,要注意判断这个差值要落在公路上。

#include<cstdio>
#include<stack>
#include<set>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<iostream>
#include<cmath>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;
const int N=1100;
const int nmax = 50010;
const double esp = 1e-8;
const double PI=3.1415926;
int n;
double hx1,hx2,hy,px1,px2,py;
struct block
{
    double x1,x2;
    bool operator <(const block &b)const
    {
        return x1<b.x1;  //盲区按左端点从小到大排序
    }
} b[nmax];//公路盲区结构体
double intera(double hx,double x2,double y2)  
{
    if(fabs(hy-y2)<esp||fabs(x2-hx)<esp)  //障碍物与房子共线或两点连线垂直x轴,直接得出返回值
        return hx;
    double k=(hy-y2)/(hx-x2);  
    return (hy-k*hx-py)/(-k);
}
int main()
{
    double ox1,ox2,oy;
    while(scanf("%lf%lf%lf",&hx1,&hx2,&hy)!=EOF)
    {
        if(hx1==0&&hx2==0&&hy==0)
            break;
        scanf("%lf%lf%lf",&px1,&px2,&py);
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%lf%lf%lf",&ox1,&ox2,&oy);
            if(oy>hy||oy<py)   //不在房子和公路之间的障碍物才不可能造成盲区
            {
                b[i].x1=-inf;
                b[i].x2=-inf;
                continue;
            }
             //房子左端点与障碍物右端点作直线,求该直线与公路的交点
            b[i].x2=intera(hx1,ox2,oy); 
             //房子右端点与障碍物左端点作直线,求该直线与公路的交点
            b[i].x1=intera(hx2,ox1,oy);
        }
        if(n==0){
            printf("%.2f\n",px2-px1);
            continue;
        }
        b[n].x1=-inf;
        b[n].x2=px1;
        b[n+1].x1=px2;
        b[n+1].x2=inf;
        sort(b,b+n+2);
        double ri=b[0].x2,maxl=(double)(-inf);  //ri为前面最右边的盲点
        for(int i=1;i<n+2;i++){
            if(b[i].x1-ri>esp){//当前点左端点大于最右端的盲区点
                  maxl=max(maxl,(b[i].x1<px2?b[i].x1:px2)-(ri>px1?ri:px1));  
            //判断最右端的盲区点是否大于公路最左边,判断当前点左端点是否小于公路最右端,取有效值
            }
            ri=max(ri,b[i].x2);
        }
        if(maxl>esp)
            printf("%.2lf\n",maxl);
      else
            printf("No View\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/clz16251102113/article/details/83088971