一只很特殊的蚂蚁,只能向坐转,并且不能经过已经走过的路。一张地图上有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; }