贪心+计算几何(叉点积)
个人认为本体用贪心解释最合理,我就是用贪心思考的此题
代码些的太挫啦
#include <iostream> #include <stdio.h> #include <stack> #include <math.h> #include <string.h> using namespace std; const int maxn=55; int m,n; int vis[maxn]; int path[maxn]; struct Point { int x,y; Point(int x=0,int y=0):x(x),y(y) { } }; struct Plant { Point po; int ind; }; struct seg { Point u,v; }; Plant pla[maxn]; int cross(Point a,Point b,Point c,Point d) { return (b.x-a.x)*(d.y-c.y)-(b.y-a.y)*(d.x-c.x); } int judge(Point a,Point b,Point c,Point d) { int c1=cross(a,b,a,c),c2=cross(a,b,a,d), c3=cross(c,d,c,a),c4=cross(c,d,c,b); if(c1*c2<0&&c3*c4<0) return 1; else return 0; } int dot(Point a,Point b,Point c,Point d) { return (b.x-a.x)*(d.x-c.x)+(b.y-a.y)*(d.y-c.y); } double length(Point a,Point b) { return sqrt(double(dot(a,b,a,b))); } double Angle(Point a,Point b,Point c) { return acos(dot(a,b,b,c)/length(a,b)/length(b,c)); } int main() { scanf("%d",&m); while(m--) { scanf("%d",&n); int i; int miny=1000,minx=1000,start; seg s[maxn]; int top=0; for(i=0;i<n;i++) { scanf("%d%d%d",&pla[i].ind,&pla[i].po.x,&pla[i].po.y); if(pla[i].po.y<miny||(pla[i].po.y==miny&&pla[i].po.x<minx)) { miny=pla[i].po.y; minx=pla[i].po.x; start=i; } } memset(vis,0,sizeof(vis)); int next=start; int tot=0; path[tot++]=start; Point pre=Point(0,pla[start].po.y); s[top].u=pre;s[top++].v=pla[start].po; int tem; for(;;) { tem=next; vis[tem]=1; double ang=acos(-1); for(i=0;i<n;i++) { if(vis[i]) continue; if(cross(pre,pla[tem].po,pla[tem].po,pla[i].po)) { int j; for(j=0;j<top;j++) { if(judge(s[j].u,s[j].v,pla[i].po,pla[tem].po)) break; } if(j==top) { double ta=Angle(pre,pla[tem].po,pla[i].po); if(ta-ang<-1e-10) { ang=ta; next=i; } else if(ta==ang) { if(length(pla[tem].po,pla[i].po)<length(pla[tem].po,pla[next].po)) next=i; } } } } if(next==tem) break; else { path[tot++]=next; pre=pla[tem].po; s[top].u=pla[tem].po; s[top++].v=pla[next].po; } } printf("%d ",tot); for(i=0;i<tot-1;i++) printf("%d ",path[i]+1); printf("%d\n",path[i]+1); } return 0; }