没有造纵坐标都是最小但是横坐标不同的数据,怎么这么不毒瘤。
解法
如果把题目名称改成瑞士卷,相信大家就已经知道怎么做了。
题中说只能左转或直行,并且路径不能交叉重叠,所以起点一定是纵坐标最小的点。如果有多个纵坐标最小的点,那就选择横坐标最小的点,但是这题数据没有在这里设坑。
只能左转,那就贪心的选择最靠右的那个点走过去。因为如果不选择最靠右的点,这个点就再也不能被选到了。因为轨迹不能右转,也不能从起点下面绕过去。这里的正确性类似凸包,逆时针遍历凸包的话所有点都一直在轨迹的左侧。
如果出现三点共线的情况,那就选距离当前点最近的点,因为不能走回头路。
以上均通过向量叉积实现,不熟悉叉积的可以去凸包模板题题解区学一下。
代码
#include<bits/stdc++.h>
namespace fast_IO
{
/**
* 没啥用的东西
*/
};
using namespace fast_IO;
struct point
{
int x,y;
point(){x=y=0x3f3f3f3f;}
point(int x,int y){this->x=x,this->y=y;}
inline point operator-(const point &rhs) const{return point(x-rhs.x,y-rhs.y);}
inline int operator*(const point &rhs) const{return x*rhs.y-y*rhs.x;}
inline bool operator==(const point &rhs) const{return x==rhs.x && y==rhs.y;}
inline friend int dis(const point lhs,const point rhs)
{
return sqrt((lhs.x-rhs.x)*(lhs.x-rhs.x)+(lhs.y-rhs.y)*(lhs.y-rhs.y));
}
};
int n,st,ed,vis[1010],cnt=1;
point a[1010];
int main()
{
in>>n,out<<n<<' ';
for(int i=1,mini=0x3f3f3f3f;i<=n;i++) in>>a[i].x>>a[i].y,st=a[i].y<mini?i:st,mini=std::min(mini,a[i].y);
vis[st]=1,out<<st<<' ';
while(cnt<n)
{
for(int i=1;i<=n;i++)
if(!vis[i])
{
ed=i;
break;
}
for(int i=1;i<=n;i++)
if(i!=ed && !vis[i] && ((a[i]-a[st])*(a[ed]-a[st])>0 ||
(a[i]-a[st])*(a[ed]-a[st])==0 && abs((a[i]-a[st]).x)<abs((a[ed]-a[st]).x))) ed=i;
vis[ed]=1,st=ed,out<<st<<' ';
cnt++;
}
fwrite(Ouf,1,p3-Ouf,stdout),fflush(stdout);
return 0;
}