Closed Fences
A closed fence in the plane is a set of non-crossing, connected line segments with N corners (3 < N < 200). The corners or vertices are each distinct and are listed in counter-clockwise order in an array {xi, yi}, i in (1..N).
Every pair of adjacent vertices defines a side of the fence. Thus {xi yi xi+1 yi+1} is a side of the fence for all i in (1..N). For our purposes, N+1 = 1, so that the first and last vertices making the fence closed.
Here is a typical closed fence and a point x,y:
* x3,y3
x5,y5 / /
x,y * * / /
/ / / /
/ * /
x6,y6* x4,y4 /
| /
| /
x1,y1*----------------* x2,y2
Write a program which will do the following:
- Test an ordered list of vertices {xi,yi}, i in (1..N) to see if the array is a valid fence.
- Find the set of fence sides that a person (with no height) who is standing in the plane at position (x,y) can "see" when looking at the fence. The location x,y may fall anywhere not on the fence.
A fence side can be seen if there exists a ray that connects (x,y) and any point on the side, and the ray does not intersect any other side of the fence. A side that is parallel to the line of sight is not considered visible. In the figure, above the segments x3,y3-x4,y4; x5,y5-x6,y6; and x6-y6-x1,y1 are visible or partially visible from x,y.
PROGRAM NAME: fence4
INPUT FORMAT
| Line 1: | N, the number of corners in the fence |
| Line 2: | Two space-separated integers, x and y, that are the location of the observer. Both integers will fit into 16 bits. |
| Line 3-N+2: | A pair of space-separated integers denoting the X,Y location of the corner. The pairs are given in counterclockwise order. Both integers are no larger than 1000 in magnitude. |
NOTE: I have added anNew test case #12 for this task. Let me know if you think it's wrong. Rob Be sure to include USACO in your mail subject!
SAMPLE INPUT (file fence4.in)
13 5 5 0 0 7 0 5 2 7 5 5 7 3 5 4 9 1 8 2 5 0 9 -2 7 0 3 -3 1
OUTPUT FORMAT
If the sequence is not a valid fence, the output is a single line containing the word "NOFENCE".
Otherwise, the output is a listing of visible fence segments, one per line, shown as four space-separated integers that represent the two corners. Express the points in the segment by showing first the point that is earlier in the input, then the point that is later. Sort the segments for output by examining the last point and showing first those points that are earlier in the input. Use the same rule on the first of the two points in case of ties.
SAMPLE OUTPUT (file fence4.out)
7 0 0 7 0 5 2 7 5 7 5 5 7 5 7 3 5 -2 7 0 3 0 0 -3 1 0 3 -3 1
解题思路:
考完试终于可以回来刷题啦,一回来就遇到大怪,这道计算几何真是让我死掉了不少脑细胞
看了一些题解,觉得都不太靠谱,还是自己写吧
首先定义线段类,使用标准式定义,并保存下两个端点,以及观察者对两个端点的视角,视角用单链表是因为取(-pi, pi],视角可能存在“两段”:
[-pi, a1]∪[a2, pi]
beColline检查两段线段是共线并存在交集,一个版本用来检查相邻的线段(有一个公共点),另一个版本则是非相邻的,比较繁琐
beCrossed检查非共线线段是否有交点,使用了text里面讲的跨立实验,因为已经算出来标准式,所以这个判断变得很简单(试试用斜率式写,判断特殊情况会烦死你)
getCovered用来做交叠:首先看两段线段的覆盖视角是否有一个公共角,存在的话,看看在公共角范围内哪个线段离观察者近,远的那条就会被它覆盖掉这个角度。
怎样判断远近呢?我使用的是参数方程,取公共部分中央角度,以观察者为源点,参数t的绝对值就是距离
以上各步骤完成后检查real(真正可以被看到的角度范围)即可
这样做最大的优点是什么呢?角度能够保存的精确信息比点多得多,也就是说,可以不用考虑误差什么的了。
看看效率如何,听说最近新增了几个刁难的数据,不过我没栽在这上面:
USER: Geterns Liu [geterns1] TASK: fence4 LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.011 secs, 2940 KB] Test 2: TEST OK [0.000 secs, 2940 KB] Test 3: TEST OK [0.000 secs, 2940 KB] Test 4: TEST OK [0.000 secs, 2940 KB] Test 5: TEST OK [0.011 secs, 2940 KB] Test 6: TEST OK [0.000 secs, 2940 KB] Test 7: TEST OK [0.011 secs, 2940 KB] Test 8: TEST OK [0.022 secs, 2940 KB] Test 9: TEST OK [0.011 secs, 2940 KB] Test 10: TEST OK [0.022 secs, 2940 KB] Test 11: TEST OK [0.000 secs, 2940 KB] Test 12: TEST OK [0.011 secs, 2940 KB]
探讨了一道复杂的计算几何题目——确定平面中闭合围栏的可见部分。通过定义线段类,实现线段间的交叉检测及可见性判断算法,最终解决了观察者视角下哪些围栏部分可见的问题。

被折叠的 条评论
为什么被折叠?



