题目链接
题目大意:一只蚂蚁一直走,只能直走和左拐,为了走尽可能多的点,应该按什么路线走。
分析:既然不能右拐,也就是按逆时针方向走,很容易想到螺旋走是最优的,而为了走尽可能多的点也就每次都走最外侧的点,起点从纵坐标最低的地方开始,也就是不断地去求凸包,然后凸包上的点,下次跳过,最后输出这个路径。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define MAIN main
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int N=1e5+10;
int sgn(double x)
{
if(fabs(x)<eps) return 0;
return x<0?-1:1;
}
struct Point
{
double x,y;
int num;
Point(double x=0,double y=0,int num=0):x(x),y(y),num(num){
}
Point operator - (Point a){
return Point(x-a.x,y-a.y);}
bool operator < (const Point &a)const{
return sgn(x-a.x)<0||(sgn(x-a.x)==0&&sgn(y-a.y)<0);
}
};
double cross(Point a,Point b){
return a.x*b.y-a.y*b.x;}
Point p[101],ch[101];
int vis[101];
int Convexhull(Point *p,int n,Point *ch,int st)
{
int cnt=1,m=0;
while(m<n)
{
for(int i=st;i<n;i++){
if(vis[p[i].num]) continue;
while(m>cnt&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<0) vis[ch[m-1].num]=0,m--;
ch[m++]=p[i];vis[p[i].num]=1;
}
cnt=m;
for(int i=n-2;i>=0;i--){
if(vis[p[i].num]) continue;
while(m>cnt&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<0) vis[ch[m-1].num]=0,m--;
ch[m++]=p[i];vis[p[i].num]=1;
}
st=0;cnt=m;
}
return m;
}
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].num,&p[i].x,&p[i].y);
}
memset(vis,0,sizeof(vis));
printf("%d ",n);
sort(p,p+n);
double min_y=1e20;
int st;
for(int i=0;i<n;i++){
if(min_y>p[i].y){
min_y=p[i].y;
st=i;
}
}
int v=Convexhull(p,n,ch,st);
for(int i=0;i<v;i++){
printf("%d ",ch[i].num);
}
printf("\n");
}
return 0;
}