在地图中找到路径

前提:

重新看数据结构,自己总结并加深印象

问题:

在二维地图中,0代表此路可以走,1代表是墙,从(1,1)坐标走到(8,8),找出路径(不考虑斜的走)
地图如下:
map[10][10] = {
1,1,1,1,1,1,1,1,1,1,
1,0,1,0,0,0,0,0,0,1,
1,0,1,1,0,0,0,0,1,1,
1,0,0,0,0,0,1,0,0,1,
1,0,0,0,1,0,1,1,0,1,
1,0,0,0,1,0,1,0,0,1,
1,0,1,0,0,0,1,0,0,1,
1,0,1,0,1,0,0,0,0,1,
1,0,0,0,1,0,0,1,0,1,
1,1,1,1,1,1,1,1,1,1};

1.栈实现

大致思路:
   1. 设置节点Node,保存一个格子的x,y 和 方向
   2. 从右边顺时针访问相邻的格子,判断相邻格子中是否是墙,如果不是墙则保存要走的方向,把相邻的格子加入栈中
   3. 如果一个格子中4个方向都走过,则栈中要弹出这个格子(也就意味着这个格子已经走到底了),返回上一个格子,再检测相邻格子是否能走
注意:
   在判断完格子a相邻格子中哪个可以走时,要在map中把格子a的位置设为1,为了防止下个格子判断相邻格子时往回判断
总结:
   回溯,要保存每个格子走过的方向
   类似于深度优先搜索,运气好可能是最短路径
伪代码 :

while(栈不为空)
{
    得到栈顶格子a
    if(此格子是终点)
    {
        return true
    }
    找到相邻位置中哪个格子可以走
    if(有格子b可以走)
    {
        地图中格子a的位置设为1
        栈中加入此格子
    }
    else
    {
        地图中格子a的位置设为0
        栈中弹出格子a
    }
}

代码 :

#include <iostream>
#include <stack>

using namespace std;

int map[10][10] =
{
      /*  1,2,3,4,5,6,7,8,9*/
        1,1,1,1,1,1,1,1,1,1,
/*1*/   1,0,1,0,0,0,0,0,0,1,
/*2*/   1,0,1,1,0,0,0,0,1,1,
/*3*/   1,0,0,0,0,0,1,0,0,1,
/*4*/   1,0,0,0,1,0,1,1,0,1,
/*5*/   1,0,0,0,1,0,1,0,0,1,
/*6*/   1,0,1,0,0,0,1,0,0,1,
/*7*/   1,0,1,0,1,0,0,0,0,1,
/*8*/   1,0,0,0,1,0,0,1,0,1,
/*9*/   1,1,1,1,1,1,1,1,1,1
};

struct Node
{
    int x;
    int y;
    int dir;
};

bool FindSrcByStack(int startX, int startY, int endX, int endY, int(*map)[10], stack<Node> & resultPath)
{
    stack<Node> storePath;
    Node startNode;
    startNode.x = startX;
    startNode.y = startY;
    startNode.dir = -1;
    storePath.push(startNode);

    while (!storePath.empty())
    {
        //拿出栈顶格子
        Node node = storePath.top();
        int x = node.x;
        int y = node.y;
        int dirIndex = node.dir;
        bool isFind = false;

        //此格子是终点
        if (x == endX && y == endY)
        {
            while (!storePath.empty())
            {
                Node node = storePath.top();
                resultPath.push(node);
                storePath.pop();
            }
            return true;
        }

        //找到相邻位置中哪个格子可以走
        int ii = x;
        int jj = y;
        while (dirIndex < 4 && !isFind)
        {
            dirIndex++;
            switch (dirIndex)
            {
            case 0:
                ii = x;jj = y + 1; break;
            case 1:
                ii = x + 1; jj = y; break;
            case 2:
                ii = x; jj = y - 1; break;
            case 3:
                ii = x + 1; jj = y; break;
            }

            if (map[ii][jj] == 0)
            {
                isFind = true;
                map[ii][jj] = 1;
                break;
            }
        }

        //有格子b可以走
        if (isFind)
        {
            //地图中格子a的位置设为1
            //栈中加入此格子
            Node nextNode;
            nextNode.x = ii;
            nextNode.y = jj;
            nextNode.dir = -1;
            storePath.top().dir = dirIndex;
            storePath.push(nextNode);
        }
        else
        {
            //地图中格子a的位置设为0
            //栈中弹出格子a
            storePath.pop();
            map[x][y] = 0;
        }
    }

    return false;
}

void Print(stack<Node> path)
{
    while (!path.empty())
    {
        Node node = path.top();
        cout << "(" << node.x << "," << node.y << ")" << endl;
        path.pop();
    }
}

结果:
这里写图片描述

2.队列实现

大致思路:
   1. 设置节点Node,保存 前面格子的位置(即格a 到 格b ,我在格b保存 格a的位置)
   2. 从格子a 右边顺时针访问相邻的格子,判断相邻格子中是否是墙,如果不是墙则保存要走的方向,把四周能走的格子全部加入队列中,并且 保存 格子a 位置
   3. 再从队列中拿出格子,反复格子2操作,有格子是最后终点 或者 队列为空
注意:
   在判断完格子a相邻格子中哪个可以走时,要在map中把格子a的位置设为1,为了防止下个格子判断相邻格子时往回判断
总结:
   需要记录上一个格子的位置,根据这个记录来显示路径
   类似于广度优先搜索,这个路径找出来肯定是最短路径
伪代码 :

while(队列不为空)
{
    从队列前面拿出格子
    if(拿出的格子是终点)
    {
        return true;
    }

    while(遍历四周格子)
    {
        if(格子是否不是墙)
        {
            加入队列
            map中设置格子处为1
        }
    }
}

代码 :

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

int map[10][10] =
{
      /*  1,2,3,4,5,6,7,8,9*/
        1,1,1,1,1,1,1,1,1,1,
/*1*/   1,0,1,0,0,0,0,0,0,1,
/*2*/   1,0,1,1,0,0,0,0,1,1,
/*3*/   1,0,0,0,0,0,1,0,0,1,
/*4*/   1,0,0,0,1,0,1,1,0,1,
/*5*/   1,0,0,0,1,0,1,0,0,1,
/*6*/   1,0,1,0,0,0,1,0,0,1,
/*7*/   1,0,1,0,1,0,0,0,0,1,
/*8*/   1,0,0,0,1,0,0,1,0,1,
/*9*/   1,1,1,1,1,1,1,1,1,1
};

struct QNode
{
    int x;
    int y;
    int preNode;
};

bool FindSrcByQueue(int startX, int startY, int endX, int endY, int(*map)[10], stack<QNode> & resultPath)
{
    queue<QNode> storePath;
    vector<QNode> tmpStoreResultPath;
    QNode startNode;
    startNode.x = startX;
    startNode.y = startY;
    startNode.preNode = -1;

    storePath.push(startNode);

    int preIndex = -1;

    while (!storePath.empty())
    {
        QNode node = storePath.front();
        tmpStoreResultPath.push_back(node);
        storePath.pop();
        preIndex++;
        node.preNode = preIndex;
        int x = node.x;
        int y = node.y;
        int dirIndex = -1;
        int ii = x;
        int jj = y;

        if (x == endX && y == endY)
        {
            QNode resultNode = tmpStoreResultPath.back();
            do
            {
                resultPath.push(resultNode);
                resultNode = tmpStoreResultPath[resultNode.preNode];
            } while (resultNode.preNode != -1);
            resultPath.push(tmpStoreResultPath[0]);
            return true;
        }

        while (dirIndex < 4)
        {   
            dirIndex ++;
            switch (dirIndex)
            {
            case 0:
                ii = x;jj = y + 1;break;
            case 1:
                ii = x + 1;jj = y;break;
            case 2:
                ii = x;jj = y - 1;break;
            case 3:
                ii = x - 1;jj = y;break;
            }

            if (map[ii][jj] == 0)
            {
                QNode newNode;
                newNode.x = ii;
                newNode.y = jj;
                newNode.preNode = preIndex;
                map[ii][jj] = 1;
                storePath.push(newNode);
            }
        }

    }

    return false;
}

void Print(stack<QNode> path)
{
    while (!path.empty())
    {
        QNode node = path.top();
        cout << "(" << node.x << "," << node.y << ")" << endl;
        path.pop();
    }
}

结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/zbbzb/article/details/80896942