USACO6.5-Closed Fences:计算几何

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

一道计算几何,需要细心做,特判几种情况,一种是点在某段篱笆的平行线上,这种情况是不能算看到的,这也是我第一次WA的原因。。。。T.T一种是将端点沿着篱笆移动一段很小的距离,这样就避免了篱笆在端点处相交的情况。还有就是按题目要求来排序。这题要是没数据的话,我肯定找不到我错在哪的 o(>﹏<)o

Executing...   Test 1: TEST OK [0.003 secs, 3508 KB]   Test 2: TEST OK [0.003 secs, 3508 KB]   Test 3: TEST OK [0.003 secs, 3508 KB]   Test 4: TEST OK [0.005 secs, 3508 KB]   Test 5: TEST OK [0.003 secs, 3508 KB]   Test 6: TEST OK [0.014 secs, 3508 KB]   Test 7: TEST OK [0.008 secs, 3508 KB]   Test 8: TEST OK [0.008 secs, 3508 KB]   Test 9: TEST OK [0.011 secs, 3508 KB]   Test 10: TEST OK [0.008 secs, 3508 KB]   Test 11: TEST OK [0.003 secs, 3508 KB]   Test 12: TEST OK [0.003 secs, 3508 KB]

All tests OK.

  1 /*
  2 TASK:fence4
  3 LANG:C++
  4 */
  5
  6 #include <iostream>
  7 #include <vector>
  8 #include <stdlib.h>
  9 #include <stdio.h>
 10 #include <cmath>
 11 using namespace std;
 12
 13 //定义点
 14 struct Point
 15 {
 16     double x;
 17     double y;
 18 };
 19 typedef Point Vector;
 20 bool operator == (const Point& p1, const Point& p2)
 21 {
 22     return fabs(p1.x - p2.x)<1e-12 && fabs(p1.y - p2.y)<1e-12;
 23 }
 24 typedef struct Point point;
 25 Vector operator - (const Point& A, const Point& B)
 26 {
 27     return Vector{A.x-B.x, A.y-B.y};
 28 }
 29 double Cross(const Vector& A, const Vector& B)
 30 {
 31     return A.x*B.y - A.y*B.x;
 32 }
 33 //叉积
 34 double multi(point p0, point p1, point p2)
 35 {
 36     return (p1.x - p0.x )*( p2.y - p0.y )-( p2.x -p0.x )*( p1.y -p0.y );
 37 }
 38 //点积
 39 double Dot(Vector A,Vector B)
 40 {
 41     return A.x*B.x+A.y*B.y;
 42 }
 43
 44 //相交返回true,否则为false, 接口为两线段的端点
 45 bool isIntersected(point s1,point e1, point s2,point e2)
 46 {
 47     if(s1==s2 || s1==e2 || e1==s2 || e1==e2)
 48     {
 49         return false;
 50     }
 51     return (max(s1.x,e1.x) >=min(s2.x,e2.x)) &&
 52            (max(s2.x,e2.x)>=min(s1.x,e1.x)) &&
 53            (max(s1.y,e1.y) >=min(s2.y,e2.y)) &&
 54            (max(s2.y,e2.y) >=min(s1.y,e1.y)) &&
 55            (multi(s1,s2,e1)*multi(s1,e1,e2)>0) &&
 56            (multi(s2,s1,e2)*multi(s2,e2,e1)>0);
 57 }
 58
 59 point ps[300];
 60 double x,y;
 61 int n ;
 62 bool check(int idx)
 63 {
 64     point pos=point {x,y};
 65     // 特判pos与线段idx平行的情况
 66     if(fabs(Cross(ps[idx]-pos,ps[idx+1]-pos))<1e-13)
 67     {
 68         return false;
 69     }
 70
 71     bool flag=false;
 72     for(int i=0; i<n; i++)
 73     {
 74         // 将ps[idx]移动一小段距离
 75         if(i==idx)
 76             continue;
 77         double dx=(ps[idx+1].x-ps[idx].x)*1e-8;
 78         double dy=(ps[idx+1].y-ps[idx].y)*1e-8;
 79
 80         if(isIntersected(pos,point {ps[idx].x+dx,ps[idx].y+dy},ps[i],ps[i+1]))
 81             flag=true;
 82     }
 83     if(!flag)
 84         return true;
 85     for(int i=0; i<n; i++)
 86     {
 87         if(i==idx)
 88             continue;
 89
 90
 91         double dx=(ps[idx].x-ps[idx+1].x)*1e-8;
 92         double dy=(ps[idx].y-ps[idx+1].y)*1e-8;
 93
 94         if(isIntersected(pos,point {ps[idx+1].x+dx,ps[idx+1].y+dy},ps[i],ps[i+1]))
 95             return false;
 96     }
 97     return true;
 98 }
 99
100
101 int main()
102 {
103     freopen("fence4.in","r",stdin);
104     freopen("fence4.out","w",stdout);
105
106     cin>>n;
107
108     scanf("%lf%lf",&x,&y);
109     for(int i=0; i<n; i++)
110     {
111         scanf("%lf%lf",&ps[i].x,&ps[i].y);
112     }
113     ps[n]=ps[0];
114
115     // 判断是否符合
116     for(int i=1; i<n; i++)
117     {
118         for(int j=0; j<i-1; j++)
119         {
120             if(isIntersected(ps[j],ps[j+1],ps[i],ps[i+1]))
121             {
122                 puts("NOFENCE");
123                 exit(0);
124             }
125         }
126     }
127
128     vector<int> ans;
129     for(int i=0; i<n; i++)
130     {
131         if(check(i))
132             ans.push_back(i);
133     }
134
135     int sz=ans.size();
136     if(sz>=2 && ans[sz-1]==n-1 && ans[sz-2]==n-2)
137         swap(ans[sz-1],ans[sz-2]);
138     printf("%d\n",sz);
139     for(int i=0; i<sz; i++)
140     {
141         if(ans[i]==n-1)
142             printf("%.0f %.0f %.0f %.0f\n",ps[ans[i]+1].x,ps[ans[i]+1].y,ps[ans[i]].x,ps[ans[i]].y);
143         else
144             printf("%.0f %.0f %.0f %.0f\n",ps[ans[i]].x,ps[ans[i]].y,ps[ans[i]+1].x,ps[ans[i]+1].y);
145     }
146
147     return 0;
148 }
				
时间: 2024-08-11 01:26:45

USACO6.5-Closed Fences:计算几何的相关文章

USACO 6.5 Closed Fences

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 pa

USACO6.4-Electric Fences:计算几何

Electric Fences Kolstad & Schrijvers Farmer John has decided to construct electric fences. He has fenced his fields into a number of bizarre shapes and now must find the optimal place to locate the electrical supply to each of the fences. A single wi

洛谷 P2735 电网 Electric Fences Label:计算几何--皮克定理

题目描述 在本题中,格点是指横纵坐标皆为整数的点. 为了圈养他的牛,农夫约翰(Farmer John)建造了一个三角形的电网.他从原点(0,0)牵出一根通电的电线,连接格点(n,m)(0<=n<32000,0<m<32000),再连接格点(p,0)(p>0),最后回到原点. 牛可以在不碰到电网的情况下被放到电网内部的每一个格点上(十分瘦的牛).如果一个格点碰到了电网,牛绝对不可以被放到该格点之上(或许Farmer John会有一些收获).那么有多少头牛可以被放到农夫约翰的电网

SPOJ AMR10A Playground(计算几何)

Playground Time limit: 2s Source limit: 50000B Memory limit: 256MB My kid's school cleared a large field on their property recently to convert it into a playing area.  The field is polygonal.  The school administration decided to separate the field i

XShell 连接虚拟机中的服务器 失败 、连接中断(Connection closed by foreign host.)

在使用XShell连接虚拟机中的服务器时,报以下错误并断开连接,之前连接还是挺稳定的,忽然就这样了 Last login: Thu Aug 10 21:28:38 2017 from 192.168.1.102 [[email protected] ~]# Socket error Event: 32 Error: 10053. Connection closing...Socket close. Connection closed by foreign host. Disconnected f

java.net.SocketException: socket closed

在使用socket编程的时候,发现当使用完getInputStream方法后,再获取OutputStream就会报 java.net.SocketException: socket closed错误 看到JAVA api中写到 java.net.Socket.getInputStream方法: getInputStream public InputStream getInputStream()throws IOException 返回此套接字的输入流. 如果此套接字具有关联的通道,则所得的输入流

!HDU 4380 三角屋内有奇数个宝藏的三角形有多少个-计算几何-(向量叉乘&amp;线段与点的关系&amp;暴力枚举)

题意:小明要买三座房子,这三个房子构成一个三角形,已知n个房子的坐标,任何三个房子都不在一条直线上,又已知有m个宝藏的坐标,问房子构成的三角形内有奇数个宝藏的三角形有多少个.数据范围:n(3~100),m(1~1000) 分析: 简单的计算几何.记住这题的做法. 三角形内的点的个数=上面的线段下面的点的个数 -- 下面两条线段下面的点的个数(或者下面一条线段减上面两条线段,看具体位置情况,所以直接取绝对值就好) n个点有n(n-1)/2条线段,不超过1W,枚举每条线段,再枚举每个宝藏的坐标(10

Opengl绘制计算几何库CGAL三角剖分结果的Demo

Ubuntu下改编了一个用CGAL计算输入点的三角剖分,并用OpenGL显示结果的C++程序. 该Demo可作为一个计算几何及绘图的框架. 代码如下: //编译命令:g++ spatial_sort.cpp -lglut -lGL -lGLU -lCGAL -lCGAL_Core -lgmp #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>   #include <CGAL/Triangulation_eucl

Ubuntu下安装cgal4.5.2计算几何库

摘要:cgal是一个开源的计算几何库, 博文记录了其编译.安装和使用方法. 1 库下载 站点:http://www.cgal.org/ 下载:https://gforge.inria.fr/frs/download.php/file/34514/CGAL-4.5.2.zip 2 解压缩.编译与安装 shell下进入解压文件夹 1)库配置文件生成命令: cmake . 提示缺少gmp和mpfr库 安装缺少的库: sudo apt-get install libgmp-dev libmpfr-dev