【分类讨论】【计算几何】【凸包】hihocoder 1582 ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 E. Territorial Dispute
题意:平面上n个点,问你是否存在一种黑白染色方案,使得对于该方案,无法使用一条直线使得黑色点划分在直线一侧,白色点划分在另一侧。如果存在,输出一种方案。
如果n<=2,显然不存在。
如果所有点共线,且n>2,只需交替染色即可。
设凸包上的点数为K,如果K==n,且n==3,不存在,如果n>3,只需交替染色即可。
如果K<n,只需凸包上点涂黑,内部点留白即可。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; struct Point{ int x,y,id; Point(const int &x,const int &y,const int &id){ this->x=x; this->y=y; this->id=id; } Point(const int &x,const int &y){ this->x=x; this->y=y; } Point(){} void read(){ scanf("%d%d",&x,&y); } }p[105],q[105]; int K; typedef Point Vector; Vector operator - (const Point &a,const Point &b){ return Vector(a.x-b.x,a.y-b.y); } int Cross(const Vector &a,const Vector &b){ return a.x*b.y-a.y*b.x; } bool cmp(const Point &a,const Point &b){ return a.x!=b.x ? a.x<b.x : a.y<b.y; } int n,T; char anss[105]; int main(){ scanf("%d",&T); for(;T;--T){ K=0; memset(anss,0,sizeof(anss)); scanf("%d",&n); for(int i=0;i<n;++i){ p[i].read(); p[i].id=i; } sort(p,p+n,cmp); if(n<=2){ puts("NO"); continue; } bool flag=1; for(int i=1;i<n-1;++i){ if(Cross(p[i]-p[i-1],p[i+1]-p[i])!=0){ flag=0; break; } } if(flag){ puts("YES"); for(int i=0;i<n;++i){ anss[p[i].id]=(i%2==0 ? 'A' : 'B'); } for(int i=0;i<n;++i){ putchar(anss[i]); } puts(""); continue; } for(int i=0;i<n;++i){ while(K>1 && Cross(q[K-1]-q[K-2],p[i]-q[K-1])<0){ --K; } q[K++]=p[i]; } for(int i=n-2,t=K;i>=0;--i){ while(K>t && Cross(q[K-1]-q[K-2],p[i]-q[K-1])<0){ --K; } q[K++]=p[i]; } --K; if(K<n){ for(int i=0;i<K;++i){ anss[q[i].id]='A'; } for(int i=0;i<n;++i){ if(!anss[i]){ anss[i]='B'; } } puts("YES"); for(int i=0;i<n;++i){ putchar(anss[i]); } puts(""); } else{ if(K>3){ for(int i=0;i<K;++i){ anss[q[i].id]=(i%2==0 ? 'A' : 'B'); } puts("YES"); for(int i=0;i<n;++i){ putchar(anss[i]); } puts(""); } else{ puts("NO"); } } } return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/