半平面交模板 HDU 1469

题意就是要判断一个多边形是否存在核。

我们可以把沿着顺时针方向走这个多边形,对于每个边向量,我们取其右边的半平面,判断交是否为空即可。

对于半平面交算法,我只理解了O(n^2)的算法,大概就是用向量去切割多边形,对于O(nlogn)的算法,我从网上各种搜集以及参考了蓝书的实现,给出了一份能看的代码。

O(n^2)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 #define maxn 1005
 7 const double eps=0.00000001;
 8 struct Point {double x,y;};
 9 struct Vector {double x,y;};
10 int Case,n,tot1,tot2;
11 Point a[maxn],b[maxn],tmp[maxn];
12
13 Vector operator - (Point x,Point y)
14 {
15     return (Vector){x.x-y.x,x.y-y.y};
16 }
17
18 bool operator == (Point x,Point y)
19 {
20     return fabs(x.x-y.x)<eps&&fabs(x.y-y.y)<eps;
21 }
22
23 double Cross(Vector a,Vector b)
24 {
25     return a.x*b.y-a.y*b.x;
26 }
27
28 double Dot(Vector a,Vector b)
29 {
30     return a.x*b.x+a.y*b.y;
31 }
32
33 void solve(void)
34 {
35     a[0]=a[n];tot1=0;
36     b[++tot1]=(Point){-1e9,-1e9};
37     b[++tot1]=(Point){-1e9,1e9};
38     b[++tot1]=(Point){1e9,1e9};
39     b[++tot1]=(Point){1e9,-1e9};
40     for (int i=1;i<=n;i++)
41     {
42         Point A=a[i];
43         Point B=a[(i+1)%n];
44         tot2=0;
45         for (int j=1;j<=tot1;j++)
46         {
47             Point C=b[j];
48             Point D=(j+1)%tot1?b[(j+1)%tot1]:b[tot1];
49             if (Cross(B-A,C-A)<=0) tmp[++tot2]=C;
50             if (fabs(Cross(B-A,C-D))>eps)
51             {
52                 Vector v=A-C;
53                 double lim=Cross(D-C,v)/Cross(B-A,D-C);
54                 tot2++;
55                 tmp[tot2].x=A.x+lim*(B-A).x;
56                 tmp[tot2].y=A.y+lim*(B-A).y;
57                 if (tmp[tot2]==C||tmp[tot2]==D) tot2--;
58                 else if (Dot(tmp[tot2]-C,tmp[tot2]-D)>0) tot2--;
59             }
60         }
61         tot1=tot2;
62         for (int i=1;i<=tot1;i++) b[i]=tmp[i];
63     }
64     Case++;
65     printf("Floor #%d\n",Case);
66     tot1?puts("Surveillance is possible."):puts("Surveillance is impossible.");
67     puts("");
68     //for (int i=1;i<=tot1;i++) printf("%.3f %.3f\n",b[i].x,b[i].y);
69 }
70
71 int main()
72 {
73     while (1)
74     {
75         scanf("%d",&n);
76         if (n==0) break;
77         for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
78         solve();
79     }
80     return 0;
81 }

O(nlogn)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 #define maxn 100005
 7 const double eps=0.00000001;
 8 struct Point {double x,y;};
 9 struct Vector {double x,y;};
10 struct Line{Point p;Vector v;double ang;};
11 Point a[maxn],b[maxn];
12 Line c[maxn],dque[maxn];
13 int n,Case;
14
15 Vector operator - (Point x,Point y)
16 {
17     return (Vector){x.x-y.x,x.y-y.y};
18 }
19
20 double Cross(Vector a,Vector b)
21 {
22     return a.x*b.y-a.y*b.x;
23 }
24
25 inline bool cmp(Line x,Line y)
26 {
27     if (fabs(x.ang-y.ang)>eps) return x.ang<y.ang;
28     return Cross(x.v,y.p-x.p)>0;
29 }
30
31 bool check(Line A,Line B,Line C)
32 {
33     Vector v=A.p-B.p;
34     double lim=Cross(B.v,v)/Cross(A.v,B.v);
35     Point tmp;
36     tmp.x=A.p.x+lim*A.v.x;
37     tmp.y=A.p.y+lim*A.v.y;
38     return Cross(C.v,tmp-C.p)>0;
39 }
40
41 int main()
42 {
43     while (1)
44     {
45         scanf("%d",&n);
46         if (n==0) break;
47         for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
48         a[0]=a[n];
49         for (int i=1;i<=n;i++)
50         {
51             c[i].p=a[i];
52             c[i].v=a[(i+1)%n]-a[i];
53             c[i].ang=atan2(c[i].v.y,c[i].v.x);
54             //printf("%.3f\n",c[i].ang);
55         }
56         sort(c+1,c+n+1,cmp);
57         int nn=1;
58         for (int i=2;i<=n;i++)
59             if (fabs(c[nn].ang-c[i].ang)>eps) c[++nn]=c[i];
60         n=nn;
61         //printf("%d\n",n);
62         dque[1]=c[1];
63         dque[2]=c[2];
64         int l=1,r=2;
65         for (int i=3;i<=n;i++)
66         {
67             while (l<r&&check(dque[r],dque[r-1],c[i])) r--;
68             while (l<r&&check(dque[l],dque[l+1],c[i])) l++;
69             dque[++r]=c[i];
70         }
71         while (l<r&&check(dque[r],dque[r-1],dque[l])) r--;
72         while (l<r&&check(dque[l],dque[l+1],dque[r])) l++;
73         printf("Floor #%d\n",++Case);
74         r-l>1?puts("Surveillance is possible."):puts("Surveillance is impossible.");
75         puts("");
76     }
77     return 0;
78 }
时间: 2024-11-22 18:48:12

半平面交模板 HDU 1469的相关文章

半平面交模板

摘自http://blog.csdn.net/accry/article/details/6070621 首先解决问题:什么是半平面? 顾名思义,半平面就是指平面的一半,我们知道,一条直线可以将平面分为两个部分,那么这两个部分就叫做两个半平面. 然后,半平面怎么表示呢? 二维坐标系下,直线可以表示为ax + by + c = 0,那么两个半平面则可以表示为ax + by + c >= 0 和ax + by + c < 0,这就是半平面的表示方法. 还有,半平面的交是神马玩意? 其实就是一个方程

半平面交 模板 poj 3335 poj 3130 poj 1474 判断半平面交是否为空集

半平面交模板 const double pi= acos(-1.0); #define arc(x) (x / 180 * pi) const double EPS = 1e-8; const int Max_N = 105; struct Point{ double x,y; Point(){} Point(double x, double y):x(x),y(y){} Point operator - (Point p){ return Point(x- p.x , y - p.y ) ;

POJ 3525 /// 半平面交 模板

题目大意: 给定n,接下来n行逆时针给定小岛的n个顶点 输出岛内离海最远的点与海的距离 半平面交模板题 将整个小岛视为由许多半平面围成 那么以相同的比例缩小这些半平面 一直到缩小到一个点时 那个点就是离海最远的点 #include <cstdio> #include <cmath> #include <vector> #include <algorithm> using namespace std; const double eps=1e-10; doubl

bzoj 2618【半平面交模板】

#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int N=505; int d,b,n,m; struct dian { double x,y; dian(double X=0,double Y=0) { x=X,y=Y; } dian operator + (const dian &a) const

Rotating Scoreboard(半平面交模板题)

Rotating Scoreboard http://poj.org/problem?id=3335 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8506   Accepted: 3357 Description This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spe

POJ 3335 Rotating Scoreboard(半平面交 模板)

题目链接:http://poj.org/problem?id=3335 Description This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spectators are seated along the edges of the polygon. We want to place a rotating scoreboard somewher

POJ3335 POJ3130 [半平面交]

终于写出自己的半平面交模板了....... 加入交点的地方用了直线线段相交判定 两个题一样,只不过一个顺时针一个逆时针(给出一个多边形的两种方式啦),反正那个CutPolygon是切掉左面 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> using names

[半平面交][最短路]JZOJ 3297 【SDOI2013】逃考

Description 高考又来了,对于不认真读书的来讲真不是个好消息.为了小杨能在家里认真读书,他的亲戚决定驻扎在他的家里监督他学习,有爷爷奶奶.外公外婆.大舅.大嫂.阿姨……小杨实在是忍无可忍了,这种生活跟监狱有什么区别!为了他亲爱的小红,为了他的dota,他决定越狱!假设小杨的家是个n*m 的矩阵,左下角坐标为(0,0),右上角坐标为(x1,y1).小杨有n 个亲戚,驻扎在矩阵里(位置不同,且不在矩阵的边上).小杨家里的每个地方都被亲戚监控着,而且只被距离最近的亲戚监控:也就是说假设小杨所

HDU 3982 半平面交+圆与多边形面积交

Harry Potter and J.K.Rowling Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 685    Accepted Submission(s): 210 Problem Description In July 31st, last month, the author of the famous novel seri