首页 > 代码库 > 半平面交模板 HDU 1469

半平面交模板 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 }

 

半平面交模板 HDU 1469