P1863 独眼兔 题解

2025/01/17 Blog

没有造纵坐标都是最小但是横坐标不同的数据,怎么这么不毒瘤。

解法

如果把题目名称改成瑞士卷,相信大家就已经知道怎么做了。

题中说只能左转或直行,并且路径不能交叉重叠,所以起点一定是纵坐标最小的点。如果有多个纵坐标最小的点,那就选择横坐标最小的点,但是这题数据没有在这里设坑。

只能左转,那就贪心的选择最靠右的那个点走过去。因为如果不选择最靠右的点,这个点就再也不能被选到了。因为轨迹不能右转,也不能从起点下面绕过去。这里的正确性类似凸包,逆时针遍历凸包的话所有点都一直在轨迹的左侧。

如果出现三点共线的情况,那就选距离当前点最近的点,因为不能走回头路。

以上均通过向量叉积实现,不熟悉叉积的可以去凸包模板题题解区学一下。

代码

#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;
}
对我博客最大的鼓励来自于你的评论(什么玩梗),欢迎选择 来回复, 也可以在 GitHub discussion 留言。

Search

    公告

    博主这下真摆烂了。我下辈子也不碰 Jekyll 和 MathJax 了!
    留言板,现在博主的精神状态非常好,有事烧纸。

    联系方式

    QQ: 33299235
    email: 33299235@qq.com
    Gmail: scp020.cn@gmail.com

    本人的其它个人主页

    洛谷
    CSDN

    友链

    拜谢stevehim(已退役,祝好)
    拜谢日记
    拜谢cppomstar

    views counting

    Document

    Table of Contents