【题目】
Description
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
【分析】
这道题的题意有点不好说明啊,如果我没有解释清楚的话去看其他博客吧。
题目大意:给出两条与 x x x 轴平行的线段 l 1 , l 2 l_1,l_2 l1,l2(以左端点横坐标 x 1 x_1 x1,右端点横坐标 x 2 x_2 x2,和纵坐标 y y y 给出),这两条直线之间还有一些平行于 x x x 轴的线段,这些线段可能会挡住一些视野,求出在 l 2 l_2 l2 上能够看完整个 l 1 l_1 l1 的最长连续的一段。
这道题,直接求最长的那段是不好求的,不如换一种角度。
对于每条中间的线段,不如先把它能够挡住的部分算出来,那么最后统计答案的时候就找出补集中的最大值就可以了。
而求挡住的部分也比较容易,直接用直线求交点求出挡住部分的两端点即可。
这道题还有几个小细节要处理:
- 有些线段可能不再 l 1 , l 2 l_1,l_2 l1,l2 的范围内
- 当一条线段的一部分与 l 1 l_1 l1 或 l 2 l_2 l2 重合时,不算挡住
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define eps 1e-8
using namespace std;
struct point
{
double x,y;
point(){}
point(double x,double y):x(x),y(y){}
point operator*(double k){return point(x*k,y*k);}
point operator+(const point &a){return point(x+a.x,y+a.y);}
point operator-(const point &a){return point(x-a.x,y-a.y);}
friend double dot(const point &a,const point &b){return a.x*b.x+a.y*b.y;}
friend double cross(const point &a,const point &b){return a.x*b.y-b.x*a.y;}
};
struct line
{
point s,t;
line(){}
line(point s,point t):s(s),t(t){}
}house,property;
pair<double,double>shadow[N];
point inter(line p,line q)
{
double s1=cross((p.s-q.s),(p.t-q.s));
double s2=cross((p.s-q.t),(p.t-q.t));
return (q.t-q.s)*(s1/(s1-s2))+q.s;
}
int main()
{
int n,i;
double x1,x2,y;
while(1)
{
int cnt=0;
scanf("%lf%lf%lf",&x1,&x2,&y),house=line(point(x1,y),point(x2,y));
scanf("%lf%lf%lf",&x1,&x2,&y),property=line(point(x1,y),point(x2,y));
if(house.s.x<eps&&house.t.x<eps&&house.s.y<eps) break;
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%lf%lf%lf",&x1,&x2,&y);
if(y>=house.s.y||y<=property.s.y) continue;
point st=inter(line(house.t,point(x1,y)),property);
point ed=inter(line(house.s,point(x2,y)),property);
if(st.x>=property.t.x||ed.x<=property.s.x) continue;
shadow[++cnt]=make_pair(max(property.s.x,st.x),min(property.t.x,ed.x));
}
double ans=0;
sort(shadow+1,shadow+cnt+1);
ans=max(ans,shadow[1].first-property.s.x);
ans=max(ans,property.t.x-shadow[cnt].second);
double R=shadow[1].second;
for(i=2;i<=cnt;++i)
{
if(shadow[i].first<=R) R=max(R,shadow[i].second);
else ans=max(ans,shadow[i].first-R),R=shadow[i].second;
}
if(ans<eps) puts("No View");
else printf("%.2f\n",ans);
}
return 0;
}