先选出最下边的点作为起点,再以起点为中心给所有点极角排序
这样就选出了当前点最右边的点,在以这个点为中心极角排序,继续选点
以这个规则路径就不会有交点,并且一直向左转弯
极角排序就是利用点的叉乘运算判断两个向量的左右,以此给所有点按中心以顺时针或逆时针方向排序
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double PI=acos(-1.0);
int sgn(double x)
{
if(fabs(x)<eps) return 0;
if(x<0) return -1;
else return 1;
}
struct Point
{
int id;
double x,y;
Point(){}
Point(double _x,double _y)
{
x=_x;y=_y;
}
Point operator - (const Point &b) const
{
return Point(x-b.x,y-b.y);
}
//叉积
double operator ^ (const Point &b) const
{
return x*b.y-y*b.x;
}
//点积
double operator * (const Point &b) const
{
return x*b.x+y*b.y;
}
///绕原点旋转角度B(弧度值),后x,y的变化
void transXY(double B)
{
double tx=x,ty=y;
x=tx*cos(B)-ty*sin(B);
y=tx*sin(B)+ty*cos(B);
}
};
double dist(Point a,Point b){return sqrt((a-b)*(a-b)); }
const int MAXN=100;
Point list[MAXN];
int ans[MAXN],top,p;
//相对于list[p]的极角排序
bool _cmp(Point p1,Point p2)
{
double tmp=(p1-list[p])^(p2-list[p]);
if(sgn(tmp)>0) return true;
else if(sgn(tmp)==0&&sgn(dist(p1,list[p])-dist(p2,list[p]))<=0)
return true;
else return false;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
double y=1000.0;
p=0;
for(int i=0;i<n;i++)
{
scanf("%d%lf%lf",&list[i].id,&list[i].x,&list[i].y);
if(list[i].y<y)
{
y=list[i].y;
p=i;
}
}
swap(list[p],list[0]);
ans[0]=list[0].id;
p=0;
for(int i=1;i<n;i++)
{
sort(list+i,list+n,_cmp);
ans[i]=list[i].id;
p=i;
}
printf("%d",n);
for(int i=0;i<n;i++)
printf(" %d",ans[i]);
printf("\n");
}
return 0;
}