USACO 6.5 Closed Fences
Posted sigongzi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USACO 6.5 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 a new 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
——————————————————————题解
做的第三道计算几何
首先nofence的判定用两条线段是否相交【此处可能有图】
然后从观察者到一个点偏上一点点,偏下一点点,扫描看相交
然后求一个交点【此处可能有图】
判断交点是否在射线上
然后找一个距离观察者距离最小交点所在篱笆
1 /* 2 LANG: C++ 3 PROG: fence4 4 */ 5 #include <iostream> 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 #include <cmath> 10 #define siji(i,x,y) for(int i=(x); i <= (y) ; ++i) 11 #define xiaosiji(i,x,y) for(int i=(x);i < (y); ++i) 12 #define ivorysi 13 #define eps 1e-8 14 #define o(x) ((x)*(x)) 15 using namespace std; 16 typedef long long ll; 17 int n; 18 struct vec{ 19 double x,y; 20 vec operator - (const vec &rhs)const{ 21 return (vec){x-rhs.x,y-rhs.y}; 22 } 23 vec operator + (const vec &rhs)const{ 24 return (vec){x+rhs.x,y+rhs.y}; 25 } 26 vec operator * (double d)const{ 27 return (vec){x*d,y*d}; 28 } 29 vec operator / (double d)const{ 30 return (vec){x/d,y/d}; 31 } 32 double norm() const{ 33 return x*x+y*y; 34 } 35 }pt[205],observer; 36 struct line { 37 vec s,t; 38 }seg[205]; 39 bool visible[205]; 40 int ans; 41 double cross(vec a,vec b) {//求叉积 42 return a.x*b.y-b.x*a.y; 43 } 44 vec intersect(line a,line b) {//求交点 45 double s1=cross(b.s-a.s,b.t-a.s),s2=cross(b.t-a.t,b.s-a.t); 46 return a.s+(a.t-a.s)*s1/(s1+s2); 47 } 48 inline bool dcmp(double a,double b=0) { 49 return fabs( a - b ) <= eps; 50 } 51 52 bool iscross(line a,line b) { 53 if(cross(a.t-a.s,b.s-a.s)*cross(a.t-a.s,b.t-a.s)>=0 || 54 cross(b.t-b.s,a.s-b.s)*cross(b.t-b.s,a.t-b.s)>=0) return false; 55 return true; 56 } 57 void init() { 58 scanf("%d",&n); 59 scanf("%lf%lf",&observer.x,&observer.y); 60 siji(i,1,n) { 61 scanf("%lf%lf",&pt[i].x,&pt[i].y); 62 } 63 siji(i,1,n-2) { 64 seg[i].s=pt[i],seg[i].t=pt[i+1]; 65 } 66 seg[n-1].s=pt[1],seg[n-1].t=pt[n]; 67 seg[n].s=pt[n-1],seg[n].t=pt[n]; 68 siji(i,1,n) { 69 siji(j,1,n) { 70 if(i==j) continue; 71 if(!iscross(seg[i],seg[j])) continue; 72 puts("NOFENCE"); 73 exit(0); 74 } 75 } 76 } 77 void checkline(line l) { 78 double shortest; 79 int num=-1; 80 siji(i,1,n) { 81 if(cross(seg[i].s-l.s,l.t-l.s)*cross(seg[i].t-l.s,l.t-l.s)>=0) continue;//射线只需要判定一个点 82 vec temp=intersect(l,seg[i])-l.s; 83 if(temp.x*(l.t.x-l.s.x) <0 || temp.y*(l.t.y-l.s.y)<0) continue;//假如交点和射线上的点相乘小于0说明是不同方向 84 if(num==-1) { 85 num=i;shortest=temp.norm(); 86 } 87 else if(shortest>temp.norm()){ 88 shortest=temp.norm(); 89 num=i; 90 } 91 } 92 if(num!=-1) visible[num]=1; 93 } 94 void solve() { 95 init(); 96 line l; 97 l.s=observer; 98 siji(i,1,n) { 99 double angle=atan2(pt[i].y-l.s.y,pt[i].x-l.s.x); 100 l.t=l.s+(vec){cos(angle+eps),sin(angle+eps)};//偏上一点点 101 checkline(l); 102 l.t=l.s+(vec){cos(angle-eps),sin(angle-eps)};//偏下一点点 103 checkline(l); 104 } 105 siji(i,1,n) { 106 if(visible[i]) ++ans; 107 } 108 printf("%d\n",ans); 109 siji(i,1,n) { 110 if(visible[i]) printf("%d %d %d %d\n", 111 (int)seg[i].s.x,(int)seg[i].s.y,(int)seg[i].t.x,(int)seg[i].t.y); 112 } 113 } 114 int main(int argc, char const *argv[]) 115 { 116 #ifdef ivorysi 117 freopen("fence4.in","r",stdin); 118 freopen("fence4.out","w",stdout); 119 #else 120 freopen("f1.in","r",stdin); 121 //freopen("f1.out","w",stdout); 122 #endif 123 solve(); 124 return 0; 125 }
以上是关于USACO 6.5 Closed Fences的主要内容,如果未能解决你的问题,请参考以下文章