如何在网格中获取两个节点之间的路径?

huangapple go评论66阅读模式
英文:

How can I get the pathes between two nodes in a grid?

问题

我想创建一个函数,可以给出在简单矩阵中两个元素之间可能路径的坐标。到目前为止,我已经设法确定是否可能存在路径,但是我在确定路径的坐标时很困扰。我考虑过使用链接列表,其中指针指向下一个可到达的相邻元素。然而,我觉得应该有一种更简单的方法来做到这一点。


更新1:

我开始按照sp2danny的建议创建解决方案,但不幸的是,与unvisitedNeighbours相关的错误非常奇怪:

unvisitedNeighbours[0].pMain=error: type
'std::queue<node,std::deque<node,std::allocator > >' does not
provide a subscript operator

还有另一个错误:

this->parent->parent->parent.parent.parent= error: invalid use of 'this' outside of a non-static member function

这些错误发生在将src元素推送到队列之后。

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

using namespace std;

#define row 5
#define col 5

struct node {
    pair<int, int> pMain;
    pair<int, int> parent;
    int index;

    node(pair<int, int> _p, pair<int, int> _parent, int _index) {
        pMain = _p;
        parent = _parent;
        int index = _index;
    }
};

// to find the path from
// top left to bottom right
bool isPath(int arr[row][col]) {
    // directions
    int dir[4][2] = {{0,  1},{0,  -1},{1,  0},{-1, 0}};

    // queue
    queue<node> unvisitedNeighbours;

    // insert the top right corner.

    node Node(node(make_pair(0, 0), make_pair(-1, -1), 0));
    unvisitedNeighbours.emplace(Node);

    std::vector<node> pathes;
    pathes.push_back(Node);

    // until queue is empty
    while (!unvisitedNeighbours.empty()) {
        node p = unvisitedNeighbours.front();
        unvisitedNeighbours.pop();

        // mark as visited
        arr[p.pMain.first][p.pMain.second] = -1;

        // destination is reached.
        if (p.pMain == make_pair(row - 1, col - 1)) {
            int index = p.index;
            while (index != 0) {
                std::cout << pathes.at(index).pMain.first << " " << pathes.at(index).pMain.second << endl;
                index = pathes.at(index).index;
            }
            return true;
        }

        // check all four directions
        for (int i = 0; i < 4; i++) {
            // using the direction array
            int a = p.pMain.first + dir[i][0];
            int b = p.pMain.second + dir[i][1];

            // not blocked and valid
            if (arr[a][b] != -1 && a >= 0 && b >= 0
                && a < row && b < col) {
                pathes.push_back(node(make_pair(a, b), p.pMain, pathes.size() - 1));
                unvisitedNeighbours.push(node(make_pair(a, b), p.pMain, pathes.size() - 1));

            }
        }
    }
    return false;
}

// Driver Code
int main() {
    // Given array
    int arr[row][col] = {{0,  0, 0,  -1, 0},
                         {-1, 0, 0,  -1, -1},
                         {0,  0, 0,  -1, 0},
                         {-1, 0, 0,  0,  0},
                         {0,  0, -1, 0,  0}};

    // path from arr[0][0] to arr[row][col]
    if (isPath(arr))
        cout << "Yes";
    else
        cout << "No";

    return 0;
}
英文:

I would like to make a function, which can give the coordinates of the possible pathes between two elements in a simple matrix. Until now, I have managed to determine, whether there could be a path between the two, however, I am pulling my hair out to determine the coordinate of pathes. I was thinking about a linked list, where the pointers is pointing to the next reachable, neighbouring element. However, I feel, that there should be a much simplier method to do that.


Update 1:

I started to create the solution according to sp2danny comment, but unfortunately, it gives me really weird errors in conncetion with unvisitedNeighbours:

> unvisitedNeighbours[0].pMain=error: type
> 'std::queue<node,std::deque<node,std::allocator<node> > >' does not
> provide a subscript operator

and there is an another error:

> this->parent->parent->parent.parent.parent= error: invalid use of 'this' outside of a non-static member function

the errors happen just after pushing the src element to the queue.

#include &lt;vector&gt;
#include &lt;iostream&gt;
#include &lt;queue&gt;
using namespace std;
#define row 5
#define col 5
struct node {
pair&lt;int, int&gt; pMain;
pair&lt;int, int&gt; parent;
int index;
node(pair&lt;int, int&gt; _p, pair&lt;int, int&gt; _parent, int _index) {
pMain = _p;
parent = _parent;
int index = _index;
}
};
// to find the path from
// top left to bottom right
bool isPath(int arr[row][col]) {
// directions
int dir[4][2] = {{0,  1},{0,  -1},{1,  0},{-1, 0}};
// queue
queue&lt;node&gt; unvisitedNeighbours;
// insert the top right corner.
node Node(node(make_pair(0, 0), make_pair(-1, -1), 0));
unvisitedNeighbours.emplace(Node);
std::vector&lt;node&gt; pathes;
pathes.push_back(Node);
// until queue is empty
while (!unvisitedNeighbours.empty()) {
node p = unvisitedNeighbours.front();
unvisitedNeighbours.pop();
// mark as visited
arr[p.pMain.first][p.pMain.second] = -1;
// destination is reached.
if (p.pMain == make_pair(row - 1, col - 1)) {
int index = p.index;
while (index != 0) {
std::cout &lt;&lt; pathes.at(index).pMain.first &lt;&lt; &quot; &quot; &lt;&lt; pathes.at(index).pMain.second &lt;&lt; endl;
index = pathes.at(index).index;
}
return true;
}
// check all four directions
for (int i = 0; i &lt; 4; i++) {
// using the direction array
int a = p.pMain.first + dir[i][0];
int b = p.pMain.second + dir[i][1];
// not blocked and valid
if (arr[a][b] != -1 &amp;&amp; a &gt;= 0 &amp;&amp; b &gt;= 0
&amp;&amp; a &lt; row &amp;&amp; b &lt; col) {
pathes.push_back(node(make_pair(a, b), p.pMain, pathes.size() - 1));
unvisitedNeighbours.push(node(make_pair(a, b), p.pMain, pathes.size() - 1));
}
}
}
return false;
}
// Driver Code
int main() {
// Given array
int arr[row][col] = {{0,  0, 0,  -1, 0},
{-1, 0, 0,  -1, -1},
{0,  0, 0,  -1, 0},
{-1, 0, 0,  0,  0},
{0,  0, -1, 0,  0}};
// path from arr[0][0] to arr[row][col]
if (isPath(arr))
cout &lt;&lt; &quot;Yes&quot;;
else
cout &lt;&lt; &quot;No&quot;;
return 0;
}

答案1

得分: 1

这部分内容的中文翻译如下:

基本上,你正在尝试找到无权图的最短路径。
这里的图是一个二维网格。

要打印路径,你只需在访问节点时跟踪它们和它们的父节点。

以下是示例代码:

#include <iostream>
#include <vector>
#include <queue>
#include <map>
using namespace std;

int dirX[] = {-1, 0, 0, 1};
int dirY[] = {0, -1, 1, 0};

bool IsValid(int& r, int& c, int &totalRow, int& totalCol)
{
    return (r >= 0 && r < totalRow && c >= 0 && c < totalCol);
}

int BFS(vector<vector<int>>& grid, pair<int, int> source, pair<int, int> destination, map<pair<int, int>, pair<int, int>>& parent)
{
    int totalRow = grid.size();
    int totalCol = grid[0].size();
    vector<vector<int>> visited(totalRow, vector<int> (totalCol, 0));
    vector<vector<int>> level(totalRow, vector<int> (totalCol, 0));
    queue<pair<int, int>> q;
    q.push(source);
    parent[source] = { -1, -1 };

    while (!q.empty())
    {
        pair<int, int> curr = q.front();
        q.pop();
        visited[curr.first][curr.second] = true;

        for (int d = 0; d < 4; d++)
        {
            int nextR = curr.first + dirX[d];
            int nextC = curr.second + dirY[d];
            if (IsValid(nextR, nextC, totalRow, totalCol) && grid[nextR][nextC] != -1 && !visited[nextR][nextC])
            {
                level[nextR][nextC] = 1 + level[curr.first][curr.second];
                visited[nextR][nextC] = true;
                parent[{nextR, nextC}] = curr;
                q.push({nextR, nextC});

                if (make_pair(nextR, nextC) == destination)
                {
                    return level[nextR][nextC];
                }
            }
        }
    }

    return -1;
}

void PrintShortestPath(vector<vector<int>> &grid, pair<int, int> source, pair<int, int> destination)
{
    map<pair<int, int>, pair<int, int>> parent;
    int shortestDistance = BFS(grid, source, destination, parent);
    if (shortestDistance == -1)
    {
        cout << "无可用路径!" << endl;
    }
    else
    {
        vector<pair<int, int>> path;
        pair<int, int> currentNode = destination;
        path.push_back(destination);
        cout << "最短距离: " << shortestDistance << endl;

        while (parent[currentNode] != make_pair(-1, -1))
        {
            path.push_back(parent[currentNode]);
            currentNode = parent[currentNode];
        }

        for (auto &curr : path)
        {
            cout << curr.first << " " << curr.second << endl;
        }
    }
}

int main()
{
    vector<vector<int>> grid
    {
        {0,  0, 0,  -1, 0},
        {-1, 0, 0,  -1, -1},
        {0,  0, 0,  -1, 0},
        {-1, 0, 0,  0,  0},
        {0,  0, -1, 0,  0}
    };

    PrintShortestPath(grid, { 0, 0 }, { 4, 4 });
}

注意:如果在Google中搜索“打印无权图的最短路径”,你将能够找到更多相关信息。

关于你在代码中遇到的错误

在构造函数中,你写了 int index = _index。由于这个原因,正确的索引值没有被分配。

所以在访问 pathes.at(index) 时发生了错误。

英文:

Basically, you're trying to find the shortest path of an unweighted graph.
Here the graph is a 2D grid.

To print the path, you just need to keep track of the nodes and their parent nodes when you're visiting them.

Here's a sample code:

#include&lt;iostream&gt;
#include&lt;vector&gt;
#include&lt;queue&gt;
#include&lt;map&gt;
using namespace std;
int dirX[] = {-1, 0, 0, 1};
int dirY[] = {0, -1, 1, 0};
bool IsValid(int&amp; r, int&amp; c, int &amp;totalRow, int&amp; totalCol)
{
return (r &gt;= 0 &amp;&amp; r &lt; totalRow &amp;&amp; c &gt;= 0 &amp;&amp; c &lt; totalCol);
}
int BFS(vector&lt;vector&lt;int&gt;&gt;&amp; grid, pair&lt;int, int&gt; source, pair&lt;int, int&gt; destination, map&lt;pair&lt;int, int&gt;, pair&lt;int, int&gt;&gt;&amp; parent)
{
int totalRow = grid.size();
int totalCol = grid[0].size();
vector&lt;vector&lt;int&gt;&gt; visited(totalRow, vector&lt;int&gt; (totalCol, 0));
vector&lt;vector&lt;int&gt;&gt; level(totalRow, vector&lt;int&gt; (totalCol, 0));
queue&lt;pair&lt;int, int&gt;&gt; q;
q.push(source);
parent[source] = { -1, -1 };
while (!q.empty())
{
pair&lt;int, int&gt; curr = q.front();
q.pop();
visited[curr.first][curr.second] = true;
for (int d = 0; d &lt; 4; d++)
{
int nextR = curr.first + dirX[d];
int nextC = curr.second + dirY[d];
if (IsValid(nextR, nextC, totalRow, totalCol) &amp;&amp; grid[nextR][nextC] != -1 &amp;&amp; !visited[nextR][nextC])
{
level[nextR][nextC] = 1 + level[curr.first][curr.second];
visited[nextR][nextC] = true;
parent[{nextR, nextC}] = curr;
q.push({nextR, nextC});
if (make_pair(nextR, nextC) == destination)
{
return level[nextR][nextC];
}
}
}
}
return -1;
}
void PrintShortestPath(vector&lt;vector&lt;int&gt;&gt; &amp;grid, pair&lt;int, int&gt; source, pair&lt;int, int&gt; destination)
{
map&lt;pair&lt;int, int&gt;, pair&lt;int, int&gt;&gt; parent;
int shortestDistance = BFS(grid, source, destination, parent);
if (shortestDistance == -1)
{
cout &lt;&lt; &quot;No path available!&quot; &lt;&lt; endl;
}
else
{
vector&lt;pair&lt;int, int&gt;&gt; path;
pair&lt;int, int&gt; currentNode = destination;
path.push_back(destination);
cout &lt;&lt; &quot;Shortest distance: &quot; &lt;&lt; shortestDistance &lt;&lt; endl;
while (parent[currentNode] != make_pair(- 1, -1))
{
path.push_back(parent[currentNode]);
currentNode = parent[currentNode];
}
for (auto &amp;curr : path)
{
cout &lt;&lt; curr.first &lt;&lt; &quot; &quot; &lt;&lt; curr.second &lt;&lt; endl;
}
}
}
int main()
{
vector&lt;vector&lt;int&gt;&gt; grid
{
{0,  0, 0,  -1, 0},
{-1, 0, 0,  -1, -1},
{0,  0, 0,  -1, 0},
{-1, 0, 0,  0,  0},
{0,  0, -1, 0,  0}
};
PrintShortestPath(grid, { 0, 0 }, { 4, 4 });
}

Note: If you search in google "Print shortest path of an unweighted graph", you'll be able to find more about it.

About the error, you're getting in your code

In the constructor, you've written int index = _index. Due to this, the correct index value was not assigned.

So at the time of accessing pathes.at(index), the error occurred.

node(pair&lt;int, int&gt; _p, pair&lt;int, int&gt; _parent, int _index)
{
pMain = _p;
parent = _parent;
index = _index;
}

huangapple
  • 本文由 发表于 2023年3月20日 22:40:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75791695.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定