zoj 1249 极角排序

来源:互联网 发布:mac os windows下载 编辑:程序博客网 时间:2024/06/05 01:10

一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.

    对于题目所输入的点,先找出最左下方的顶点(即纵坐标最小的顶点),然后对剩下的顶点按照对与左下点的极角排序,然后反复找最左下的点,反复进行极角排序,同时记录排序后左下的顶点.
    极角排序方法:利用叉积,看向量p1和p2的叉积是否小于零,是则说明p1在p2逆时针方向,即p1的极角比p2的大,极角相同则按离p0距离降序排序.


const double eps = 1e-8 ;double  add(double x , double y){        if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;        return x + y ;}struct  Point{        double x , y ;        int id ;        Point(){}        Point(double _x , double _y):x(_x),y(_y){}        Point operator + (Point o){              return Point(add(x , o.x) , add(y , o.y)) ;        }        Point operator - (Point o){              return Point(add(x , -o.x) , add(y , -o.y)) ;        }        Point operator * (double o){              return Point(x*o , y*o) ;        }        double operator ^(Point o){               return add(x*o.y , -y*o.x) ;        }        double dist(Point o){               return sqrt((x-o.x)*(x-o.x) + (y-o.y)*(y-o.y)) ;        }        void  read(){              scanf("%d" , &id) ;              scanf("%lf%lf" ,&x , &y) ;        }};Point  po[108] ;Point ox ;bool cmp(Point a , Point b){     double t = (a - ox) ^ (b - ox) ;     if(t < 0) return 0 ;     if(t > 0) return 1 ;     return a.dist(ox) < b.dist(ox) ;}int  main(){     int t  , k  , n , i  , j  , T = 1 ;     vector<int> lis;     cin>>t ;     while(t--){          cin>>n ;          for(i = 0 ; i < n ; i++){              po[i].read() ;              if(po[0].y > po[i].y) swap(po[0] , po[i]) ;          }          lis.clear() ;          ox = po[0] ;          lis.push_back(ox.id) ;          for(i = 1 ; i < n ; i++){              sort(po+i , po+n , cmp) ;              ox = po[i] ;              lis.push_back(ox.id) ;          }          printf("%d" , lis.size()) ;          for(i = 0 ; i < lis.size() ; i++) printf(" %d" ,lis[i]) ;          puts("") ;     }     return 0 ;}


0 0