数据结构-求解迷宫问题带环最短路径问题

带环最短路径问题

首先,构造地图:
这里写图片描述

首先构造一个多通路并且带环的迷宫。

思路与之前的求多通路的最短路径一样,需要先遍历完所有的可落脚点,将最短路径保存在最小路径栈中,与之不同的是,标记方式发生了变化,这次不能是简单标记为2,而是应该标记为它的路径长度(大致),然后比较时,就可以直接比较数值,如果当前路径走到该点的路径步数比之前的值小,我就可以走这条路,继续走。
辅助函数:由于一些判断条件和以前的问题判断条件已经发生变化了,所以需要创建考虑判断条件。

int ExitWithCycle(Maze* m,Point pt,Point entry)//判断依据没有变
{
    (void)m;
    //1当前点是不是入口,若为入口,就不是出口
    if(pt.x==entry.x&&pt.y==entry.y)
    {
        return 0;
    }
    //2.如果当前点在边界上,就是出口
    if(pt.x==0||pt.y==0||pt.x== ROW-1||pt.y==COL-1)
    {
        return 1;
    }
    return 0;
}
//标记方式变了
void MarkWithCycle(Maze* m,Point cur,Point pre)
{
    //先判断是入口点的情况,不能+1,应该直接赋值为2;
    if(pre.x==-1&&pre.y==-1)
    {
        m->maze[cur.x][cur.y]=2;
        return;
    }
    //取出pre_value
    //让这个点的值=pre_value+1
    m->maze[cur.x][cur.y]=m->maze[pre.x][pre.y]+1;

}
//判断条件变了
int CanStayWithCycle(Maze* m,Point cur,Point pre)
{
    if(m==NULL)
    {
        return 0;
    }
    (void)m;
    //0.在地图外
    if(cur.x<0||cur.x>=ROW||cur.y<0||cur.y>=COL)
    {
        return 0;
    }
    //1.如果当前点是1,这是可以直接落脚的
    if(m->maze[cur.x][cur.y]==1)
    {
        return 1;
    }
    //2.当前点如果已经走过了,比较cur对应的值和pre的值的大小关系
    //   a.cur_value 7,pre_value 5 应该落脚 更短
    //   b.cur_value 6,pre_value 5 不应该落脚 一样,没必要
    //   c.cur_value 5,pre_value 5 不应该落脚 更长
    if(m->maze[pre.x][pre.y]+1<m->maze[cur.x][cur.y])
    {
        return 1;
    }
    return 0;

}

实现函数:

void _GetShortPathWithCycle(Maze* m,Point cur,Point pre,Point entry,SeqStack* cur_path,SeqStack* short_path)
{
    printf("(%d,%d)\n",cur.x,cur.y);
    //1.判定当前点是否能落脚(判定规则变了)
    if(!CanStayWithCycle(m,cur,pre))
    {
        return;
    }
    //2.标记当前点,标记规则变了,并且将当前点插入到cur_path
    MarkWithCycle(m,cur,pre);
    SeqStackPush(cur_path,cur);
    pre=cur;
    //3.判定当前点是否是出口
    if(ExitWithCycle(m,cur,entry))
    {
        //  是出口,要拿cur_path和short_path进行pk(或者short空栈),把比较短的路径保存到short_path(seqstackassign)
        //  不管当前这条路径是不是比较短的都要进行回溯。
        printf("找到了一条路径\n");
        if(cur_path->size<short_path->size||short_path->size==0)
        {
            SeqStackAssign(cur_path,short_path);
            printf("找到了一条比较短的路径\n");
        }
        SeqStackPop(cur_path);
        return;
    }
    //4.不是出口,探测四个方向。(顺时针)
    Point up=cur;
    up.x-=1;
    _GetShortPathWithCycle(m,up,pre,entry,cur_path,short_path);

    Point right=cur;
    right.y+=1;
    _GetShortPathWithCycle(m,right,pre,entry,cur_path,short_path);

    Point down=cur;
    down.x+=1;
    _GetShortPathWithCycle(m,down,pre,entry,cur_path,short_path);

    Point left=cur;
    left.y-=1;
    _GetShortPathWithCycle(m,left,pre,entry,cur_path,short_path);
    //5.如果四个方向都探测过了,就出栈回溯
    SeqStackPop(cur_path);
    return;
}
void GetShortPathWithCycle(Maze* maze,Point entry)
{
    SeqStack cur_path;
    SeqStack short_path;
    SeqStackInit(&cur_path);
    SeqStackInit(&short_path);
    Point pre={-1,-1};//虚拟一个非法点
    _GetShortPathWithCycle(maze,entry,pre,entry,&cur_path,&short_path);//5个参数
    MazeSeqStackPrint(&short_path,"最短路径为:");
}

结果如下:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值