小算法系列-迷宫最短路径

这个实现方法非常好,不但找出路径还找出了最短路径。使用“权值”方法来判断,简洁清楚,很喜欢,收藏~

 

有一个二维数组,0表示路,-1表示墙,求其中任意两点的最短路径。

我们先看,怎么求一条路径:求两点路径是一个数据结构上的典型的迷宫问题,很多数据结构的书上都有介绍,解决办法如下:

从一点开始出发,向四个方向查找,每走一步,把走过的点的值+1(即本节点值+1),防止重复行走,并把走过的点压入堆栈(表示路径),如果遇到墙、或者已走过的点则不能前进,如果前方已经无路可走,则返回,路径退栈,这样递归调用,直到找到终点为止。

迷宫如下图所示:  

 

     


(2, 1)(6, 8),程序如下所示:

struct Postion
{
    
int _X, _Y;

    Postion() {}
    Postion(
int X, int Y)
        : _X(X), _Y(Y) {}
};

bool isCanGo(const 
int prePosValue,
             const 
int posX,
             const 
int posY)
{
    
if (   posX < 0 || posX > 9        // 越界
        || posY < 0 || posY > 9        
        || maze[posX][posY] == -1    
// 
        || maze[posX][posY] >= 1)    // 走过
     {
        
return false;
    }

    
return true;
}


stack<Postion> path__;            
//路径
        
Postion offset[4];                
//路径

bool shortestPath(stack<Postion> &path,
                  const Postion &start,
                  const Postion &end)
{
    
if (   start._X == end._X 
        && start._Y == end._Y)
     {
        path__ = path;
        
return true;
    }
    
    
for (int i = 0; i < 4; i++)
     {
        
int nNextPos_X = start._X + offset[i]._X;
        
int nNextPos_Y = start._Y + offset[i]._Y;

        
if (isCanGo(maze[start._X][start._Y], nNextPos_X, nNextPos_Y))
         {
            maze[nNextPos_X][nNextPos_Y] = maze[start._X][start._Y] + 1;

            path.push(Postion(nNextPos_X, nNextPos_Y));

            
if (shortestPath(path, Postion(nNextPos_X, nNextPos_Y), end))
                
return true;

            path.pop();
        }
    }

    
return false;
}

int main(int argc, char* argv[])
{
    offset[0]._X = -1;    offset[0]._Y = 0;    
// 
    offset[1]._X = 1;    offset[1]._Y = 0;    // 
    offset[2]._X = 0;    offset[2]._Y = -1;    // 
    offset[3]._X = 0;    offset[3]._Y = 1;    // 

    printMat(maze);


    Postion start(2, 1), end(6, 8);
    maze[start._X][start._Y] = 1;            
// 置起点值1, 防止走回起点
    shortestPath(stack<Postion>(), start, end);

    printPath(path__);
    printMat(maze);

    
return 0;
}

这时,我们经过运算,到达终点,有44步之多。如果我们调整调用offset的顺序,即先左右,后上下,可能会得到更短的路径,但无法确保在任何情况下都能得到最短路径。

得到最短路径的方法,解决方法如下:

每走一步,就对前方的节点赋值为此节点+1,走过的路径也可以重复行走。但有一个条件,就是本节点+1必须小于已走过的节点的权值(墙不能走),这样走遍所有的节点,记录最短的路径。

主要修改了以下两个函数:

bool isCanGo(const int prePosValue,
             const 
int posX,
             const 
int posY)
{
    
if (   posX < 0 || posX > 9        // 越界
        || posY < 0 || posY > 9        
        || maze[posX][posY] == -1)    
// 
     {
        
return false;
    }

    
if (maze[posX][posY] == 0)    // 未走过
        return true;
    
else                        // 更近的路径
        return (prePosValue + 1) < maze[posX][posY];
}

void shortestPath(stack<Postion> &path,
                  const Postion &start,
                  const Postion &end)
{
    
if (   start._X == end._X 
        && start._Y == end._Y)
     {
        
if (path.size() < path__.size() || path__.empty())    // 更短的路径
            path__ = path;
        
return;
    }
    
    
for (int i = 0; i < 4; i++)
     {
        
int nNextPos_X = start._X + offset[i]._X;
        
int nNextPos_Y = start._Y + offset[i]._Y;

        
if (isCanGo(maze[start._X][start._Y], nNextPos_X, nNextPos_Y))
         {
            maze[nNextPos_X][nNextPos_Y] = maze[start._X][start._Y] + 1;

            path.push(Postion(nNextPos_X, nNextPos_Y));

            shortestPath(path, Postion(nNextPos_X, nNextPos_Y), end);

            path.pop();
        }
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值