一只很特殊的蚂蚁,只能向坐转,并且不能经过已经走过的路。一张地图上有n个食物让蚂蚁去采集,求蚂蚁经过食物的顺序。
一开始想偷懒,直接甩graham凸包模版上去,加了一条判断和搜索点的重排。。果断WA
好吧果然还是不能偷懒啊!每确定一个点以它为起点找逆时针一个个碰到的点。。其实大概或许就是卷包裹求凸包了吧。。不太了解的说。。
判断点用的就是叉积了
//Memory: 260K
//Time: 0MS
#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
bool use[100];
struct POINT
{
double x,y;
int num;
};POINT PointSet[100],ch[100];
double dist(POINT p1,POINT p2)
{
return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );
}
/******************************************************************************\
r=multiply(sp,ep,op),得到(sp-op)和(ep-op)的叉积
r>0:ep在矢量opsp的逆时针方向;
r=0:opspep三点共线;
r<0:ep在矢量opsp的顺时针方向
\******************************************************************************/
double multiply(POINT sp,POINT ep,POINT op)
{
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
void getans(int n)
{
int i,k=0,sum=1,minp=50,p=0;
bool flag;
while(sum<=n)
{
minp=100000;
flag=true;
for(i=1;i<=n;i++)
{
if(!use[ PointSet[i].num ])
{
if(flag)
{ minp=i;
flag=false;
}
else
{
if(multiply(PointSet[minp],PointSet[i],PointSet[p])<0|| // 极角更小
(multiply(PointSet[minp],PointSet[i],PointSet[p])==0) && /* 极角相等,距离更短 */
dist(PointSet[p],PointSet[minp])>dist(PointSet[p],PointSet[i]))
minp=i;
}
}
}
ch[sum++]=PointSet[minp];
use[ PointSet[minp].num ]=true;
p=minp;
}
}
int main()
{
int n,cas,i;
cin>>cas;
while(cas--)
{
cin>>n;
memset(use,0,sizeof(use));
double miny=1000000;
for(i=1;i<=n;i++)
{
cin>>PointSet[i].num>>PointSet[i].x>>PointSet[i].y;
miny=min(miny,PointSet[i].y);
}
PointSet[0].x=0;PointSet[0].y=miny;
getans(n);
cout<<n;
for(i=1;i<=n;i++)
cout<<" "<<ch[i].num;
cout<<endl;
}
return 0;
}