题意就是要判断一个多边形是否存在核。
我们可以把沿着顺时针方向走这个多边形,对于每个边向量,我们取其右边的半平面,判断交是否为空即可。
对于半平面交算法,我只理解了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 }