HDU3685 几何+重心+凸包+判定锐角三角形

先算重心!!!!!!再算凸包!!!!!!!

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 }    

 

你可能感兴趣的:(HDU)