一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.
对于题目所输入的点,先找出最左下方的顶点(即纵坐标最小的顶点),然后对剩下的顶点按照对与左下点的极角排序,然后反复找最左下的点,反复进行极角排序,同时记录排序后左下的顶点.
极角排序方法:利用叉积,看向量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 ;
}