poj 2074 Line of Sight (计算几何,细节题)

Line of Sight
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 3935   Accepted: 1229

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

Source

 
终于A了。
细节比较多。
这题的大致思路是,先将结构体按照x2排序
然后从左往右扫,求得在li上的两点p1,p2 分别使得 p1.x  li[i].x2 house.x1 和 p2.x li[i+1].x1 house.x2三点共线。
然后取(p2.x-p1.x)最大的一组。
不过细节比较多。
 
说下这题需要注意的地方吧:
  1. 只说了房子一定在line上面,而障碍物是可能不在房子和线之间的。如果障碍物在房子以上或者线以下就跳过(包括相等)
  2. 第一个点和最后一个点要特殊处理。因为第一个的p1左边到li.x1和 第二个点的p2右边到li.x2都是有解的范围。
  3. 可能没有障碍物(n==0),此时答案为li.x2-li.x1
  4. 可能有障碍物,但是障碍物没起作用,就是说障碍物没有挡住任何视线,此时答案同上。所以3,4点可以和在一起考虑。可以用一个boolean变量beblocked记录是否有被遮挡的情况。如果最后发现没有遮挡的情况,那么答案为li.x2-li.x1;
  5. 求得到的p1,p2点可能不在line上,要注意维护下边界。
  6. 以上的情况,对于第二点中提及的特殊处理中。。也不要漏写。
  1 /*************************************************************************
  2     > File Name: code/poj/2074.cpp
  3     > Author: 111qqz
  4     > Email: rkz2013@126.com 
  5     > Created Time: 2015年11月08日 星期日 10时26分28秒
  6  ************************************************************************/
  7 
  8 #include<iostream>
  9 #include<iomanip>
 10 #include<cstdio>
 11 #include<algorithm>
 12 #include<cmath>
 13 #include<cstring>
 14 #include<string>
 15 #include<map>
 16 #include<set>
 17 #include<queue>
 18 #include<vector>
 19 #include<stack>
 20 #include<cctype>
 21 #define fst first              
 22 #define sec second      
 23 #define lson l,m,rt<<1
 24 #define rson m+1,r,rt<<1|1
 25 #define ms(a,x) memset(a,x,sizeof(a))
 26 using namespace std;
 27 const double eps = 1E-8;
 28 const int dx4[4]={1,0,0,-1};
 29 const int dy4[4]={0,-1,1,0};
 30 typedef long long LL;
 31 const int inf = 0x3f3f3f3f;
 32 const int N=1E4+6;
 33 int n;
 34 
 35 int dblcmp(double d)
 36 {
 37     return d<-eps ?-1:d>eps;
 38 }
 39 struct node
 40 {
 41     double x1,x2,y;
 42 }obs[N],house,li;
 43 
 44 struct point
 45 {
 46     double x,y;
 47 };
 48 
 49 bool cmp (node a,node b )
 50 {
 51     return a.x2<b.x2;
 52 }
 53 
 54 int main()
 55 {
 56   #ifndef  ONLINE_JUDGE 
 57    freopen("in.txt","r",stdin);
 58   #endif
 59 
 60    while (scanf("%lf %lf %lf",&house.x1,&house.x2,&house.y)!=EOF)
 61     {
 62     if (dblcmp(house.x1)==0&&dblcmp(house.x2)==0&&dblcmp(house.y)==0) break;
 63     scanf("%lf %lf %lf",&li.x1,&li.x2,&li.y);
 64     scanf("%d",&n);
 65     for ( int i = 0 ; i < n ; i++ ) scanf("%lf %lf %lf",&obs[i].x1,&obs[i].x2,&obs[i].y);
 66 
 67     sort(obs,obs+n,cmp);
 68     double sum = -1 ;
 69     
 70     point p1,p2;
 71     double k;
 72     bool beblocked = false;
 73         for ( int i = 0 ;i <n-1 ; i++)   //最后一个只算右端点就行      
 74     {
 75         if (dblcmp(obs[i].y-house.y)>=0||dblcmp(obs[i].y-li.y)<=0) continue;
 76         else beblocked = true;
 77         if (dblcmp(obs[i].x2-obs[i+1].x1)<0)
 78         {                                                                                                   
 79         if (dblcmp(obs[i].x2-house.x1)==0)
 80         {
 81             p1.x=house.x1; 
 82         }
 83         else
 84         {
 85             k = (house.y-obs[i].y)*1.0/(house.x1-obs[i].x2);
 86             p1.x = house.x1-(house.y-li.y)/k;
 87 
 88         }
 89         if (dblcmp(obs[i+1].x1-house.x2)==0)
 90         {
 91             p2.x=house.x2;
 92         }
 93         else
 94         {
 95             k = (house.y-obs[i+1].y)*1.0/(house.x2-obs[i+1].x1);
 96             p2.x = house.x2-(house.y-li.y)/k;
 97         }
 98         p1.x = max(p1.x,li.x1);  //边界维护
 99         p2.x = min(p2.x,li.x2);
100 //        cout<<"p1.x:"<<p1.x<<" p2.x"<<p2.x<<endl;
101         if (dblcmp(p2.x-p1.x)>0)  //求连续的最大段。。。不是求和。。认真读题。
102         {
103             sum = max(sum,p2.x-p1.x);
104             beblocked  = true;
105 //            cout<<"sum:"<<sum<<endl;
106         }                                             
107         }
108     }
109     //最后一个特殊处理:
110     if (dblcmp(house.x1-obs[n-1].x2)==0)
111     {
112         p1.x = house.x1;
113     }
114     else
115     {
116         k = (house.y-obs[n-1].y)/(house.x1-obs[n-1].x2);
117         p1.x = house.x1-house.y/k;
118 //        cout<<"k:"<<k<<endl;
119     }
120 //    cout<<"p1.x:"<<p1.x<<" li.x2:"<<li.x2<<" minus:"<<li.x2-p1.x<<endl;
121     if (dblcmp(house.y-obs[n-1].y)>0&&dblcmp(li.y-obs[n-1].y)<0)
122         sum = max(sum,li.x2-p1.x),beblocked = true;
123 
124     //第一个要要单独处理
125         
126     if (dblcmp(house.x2-obs[0].x1)==0)
127     {
128         p1.x=house.x2;
129     }
130     else
131     {
132         k = (house.y-obs[0].y)/(house.x2-obs[0].x1);
133         p1.x = house.x2-house.y/k;
134 //        cout<<"k:"<<k<<endl;
135     }
136     if (dblcmp(house.y-obs[0].y)>0&&dblcmp(li.y-obs[0].y)<0)
137         sum = max(sum,p1.x-li.x1),beblocked = true;
138         
139     if (!beblocked)
140     {
141         sum = li.x2-li.x1;
142     }
143     if (dblcmp(sum)>0)
144     {
145         printf("%.2f
",sum);
146     }
147     else
148     {
149         puts("No View");
150     }
151         
152 
153 
154     }
155  #ifndef ONLINE_JUDGE  
156   #endif
157   fclose(stdin);
158     return 0;
159 }
View Code
原文地址:https://www.cnblogs.com/111qqz/p/4947417.html