版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lidengdengter/article/details/82056016
n个点,蚂蚁从y坐标最小的点开始逆时针爬行,写出经过点的序号。
每次选点都只能从剩下的点中选择最靠右的,用叉积排序求解。题解有说这是凸包变种,可用凸包求解(写的时候没写对),涉及卷包裹算法,也可以用极角排序,涉及Granham Scan算法。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100;
const double inf=1e9;
const double eps=1e-8;
int sgn(double x){
if(fabs(x)<eps)
return 0;
if(x<0)
return -1;
else return 1;
}
struct point{
double x,y;
int index;
point(){}
point(double sx,double sy):x(sx),y(sy){}
point operator +(const point &w)const{ //相减
return point(x+w.x,y+w.y);
}
point operator -(const point &w)const{ //相减
return point(x-w.x,y-w.y);
}
double operator ^(const point &w)const{ //叉积
return x*w.y-y*w.x;
}
double operator *(const point &w)const{ //点积
return x*w.x+y*w.y;
}
}p[N];
double dist(point a,point b){
return sqrt((a-b)*(a-b));
}
int pos;
bool cmp1(point a,point b){
double mp=(a-p[pos]^(b-p[pos]));
if(sgn(mp)==0)
return dist(p[pos],a)<dist(p[pos],b);
else if(sgn(mp)<0)
return false;
else
return true;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%lf%lf",&p[i].index,&p[i].x,&p[i].y);
if(p[i].y<p[0].y||(p[i].y==p[0].y&&p[i].x<p[0].x))
swap(p[0],p[i]);
}
pos=0;
for(int i=1;i<n;i++){
sort(p+i,p+n,cmp1);
pos++;
}
printf("%d ",n);
for(int i=0;i<n;i++)
printf("%d%c",p[i].index,i==n-1?'\n':' ');
}
return 0;
}