贪心+计算几何(叉点积)
个人认为本体用贪心解释最合理,我就是用贪心思考的此题
代码些的太挫啦
#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;
}