先算重心!!!!!!再算凸包!!!!!!!
View Code
1 /* 2 几何+重心 3 */ 4 #include<stdio.h> 5 #include<string.h> 6 #include<stdlib.h> 7 #include<algorithm> 8 #include<iostream> 9 #include<queue> 10 //#include<map> 11 #include<math.h> 12 using namespace std; 13 typedef long long ll; 14 //typedef __int64 int64; 15 const int maxn = 50005; 16 const int inf = 0x7fffffff; 17 const double pi=acos(-1.0); 18 const double eps = 1e-8; 19 struct point { 20 double x,y; 21 bool operator < ( const point &l ) const { 22 return y<l.y||( l.y==y&&x<l.x ); 23 } 24 }; 25 struct point2{ 26 double x,y,area; 27 }; 28 point myp[ maxn ],res[ maxn ]; 29 point2 b[ maxn ];//由一个三角形得到的新“点“ 30 31 double xmult( point sp,point ep,point op ){ 32 return (sp.x - op.x) * (ep.y - op.y)-(ep.x - op.x) * (sp.y - op.y); 33 } 34 35 int graham( int n,point pnt[] ){ 36 int i, len, k = 0; 37 int top = 1; 38 sort(pnt, pnt + n); 39 if (n == 0) return 0; res[0] = pnt[0]; 40 if (n == 1) return 1; res[1] = pnt[1]; 41 if (n == 2) return 2; res[2] = pnt[2]; 42 for (i = 2; i < n; i++) { 43 while (top && xmult(res[ top ], pnt[ i ], res[top-1])>=0 )//( cross : from top to i ) 44 top--; 45 res[++top] = pnt[i]; 46 } 47 len = top; res[++top] = pnt[n - 2]; 48 for (i = n - 3; i >= 0; i--) { 49 while (top!=len && xmult(res[ top ], pnt[ i ], res[top-1])>=0 ) 50 top--; 51 res[++top] = pnt[i]; 52 } 53 return top; // 返回凸包中点的个数 54 }//res 存储着凸包里面的点 55 56 point get_grav( int n,point p[] ){ 57 double ans_x,ans_y; 58 double sum_Area=0; 59 int cnt=0;//被切割为三角形的个数 60 for( int i=2;i<n;i++ ){ 61 double tmp=xmult( p[ i-1 ],p[ i ],p[ 0 ] ); 62 b[ cnt ].x=p[ 0 ].x+p[ i-1 ].x+p[ i ].x; 63 b[ cnt ].y=p[ 0 ].y+p[ i-1 ].y+p[ i ].y; 64 b[ cnt ].area = tmp; 65 sum_Area += tmp; 66 cnt++; 67 } 68 ans_x=ans_y=0; 69 for( int i=0;i<cnt;i++ ){ 70 ans_x+=b[ i ].x*b[ i ].area; 71 ans_y+=b[ i ].y*b[ i ].area; 72 } 73 ans_x/=(3.0*sum_Area); 74 ans_y/=(3.0*sum_Area);//重心坐标 75 point grav; 76 grav.x=ans_x,grav.y=ans_y; 77 return grav;//返回重心坐标 78 } 79 double dist( point a,point b ){ 80 return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); 81 } 82 bool solve( point a,point b,point now ){//判断会不会出现钝角 83 double dis1,dis2,dis3; 84 dis1 = dist( a,b ); 85 dis2 = dist( a,now ); 86 dis3 = dist( b,now ); 87 if( (dis1+dis2-dis3>eps)&&(dis1+dis3-dis2>eps) ) 88 return true;//这两个角必须为锐角,才可能保证 now 这个点在a,b“之间“ 89 return false; 90 } 91 92 int main(){ 93 int ca; 94 scanf("%d",&ca); 95 while( ca-- ){ 96 int n; 97 scanf("%d",&n); 98 for( int i=0;i<n;i++ ) 99 scanf("%lf%lf",&myp[ i ].x,&myp[ i ].y); 100 point grav; 101 grav = get_grav( n,myp ); 102 int CNT = graham( n,myp ); 103 //printf("CNT:%d\n",CNT); 104 //for( int i=0;i<CNT;i++ ) 105 //printf("%d:%lf %lf\n",i,res[i].x,res[i].y); 106 //printf("grav:%lf %lf\n",grav.x,grav.y); 107 int ans=0; 108 res[ CNT ]=res[ 0 ]; 109 for( int i=1;i<=CNT;i++ ){ 110 if( solve( res[i-1],res[i],grav )==true ) 111 ans++;//,printf("ans:%d %d\n",i-1,i); 112 } 113 printf("%d\n",ans); 114 } 115 return 0; 116 }