我正在尝试实现一个问题的解决方案,其中我需要在从源到目标的递归中找到迷宫中的路径。
假设这是迷宫:
S X X X X X
. . . . . X
X . X X X X
X . X X X X
. . . X . G
X X . . . X
X-阻塞路径
.-开放路径
S-开始
G -Goal
我编写了以下代码来实现解决方案,但它给了我一个分段错误。 如果有人能告诉我我做错了什么,我会很高兴。
我的解决方案是
#include<iostream>
using namespace std;
void printGrid(char grid[6][6])
{
for(int i=0;i<6;i++)
{
for(int j=0;j<6;j++)
{
cout<<grid[i][j]<<" ";
}
cout<<"\n";
}
}
bool isValidPoint(char grid[6][6],int x,int y)
{
if(x<0 || x>5 || y<0 || y>5)
{
return false;
}
if(grid[x][y]=='X')
{
return false;
}
return true;
}
bool traceMaze(char grid[6][6],int x,int y)
{
if(!isValidPoint(grid,x,y))
{
return false;
}
if(grid[x][y]=='G')
{
return true;
}
grid[x][y] = '+';
if(traceMaze(grid,x-1,y)){return true;}
if(traceMaze(grid,x,y+1)){return true;}
if(traceMaze(grid,x+1,y)){return true;}
if(traceMaze(grid,x,y-1)){return true;}
grid[x][y] = '.';
return false;
}
int main()
{
char grid[6][6] = {{'S','X','X','X','X','X'},{'.','.','.','.','.','X'},{'X','.','X','X','X','X'},{'X','.','X','X','X','X'},{'.','.','.','X','.','G'},{'X','X','.','.','.','X'}};
cout<<"Initial grid is as follows :\n";
printGrid(grid);
cout<<"\nStarting at : (0,0)\nTracing the path to the Goal\n";
cout<<traceMaze(grid,0,0)<<"\n";
cout<<"\nFinal grid is as follows :\n";
printGrid(grid);
return 0;
}
PS:我假设迷宫的大小为6X6 ......
Correct Solution :
我没有检查过我正在查看最后追踪路径的'+'。
所以现在我在那里应用了一个检查并将isValidPoint
函数转换为:
bool isValidPoint(char grid[6][6],int x,int y)
{
if(x<0 || x>5 || y<0 || y>5)
{
return false;
}
if(grid[x][y]=='X' || grid[x][y]=='+')
{
return false;
}
return true;
}
感谢您的帮助:)
去年我把这个问题作为全职面试。
答案 0 :(得分:3)
没有什么能阻止traceMaze函数无限递归。即它将从一个网格点转到下一个网格点,然后再返回到原始网格点。
最简单的解决方法是不要对待&#34; +&#34;在它作为一个有效的点进入(因为你已经在这条路径中)。
答案 1 :(得分:0)
黑暗的答案在我看来是有效的。
您的搜索范围是从0,0开始。然后它转到0,1,然后从那里回到0,0,然后再回到0,1 ......你应该标记你已经访问过的方块,而不是再去那里。 &#39; +&#39;很好,但是一旦你设置它就不应该清除它,你应该在isValidPoint中检查它。
答案 2 :(得分:0)
你正在做的是迷宫的深度优先遍历。您正在使用.
更改+
以跟踪已访问的点,但是在完成后您又将其更改为.
。这就是问题所在。
假设A
和B
是迷宫的相邻单元格。当您浏览A
时,将A
更改为+
并递归遍历其邻居(包括B
),然后将A
更改为再次.
。然后,当您浏览B
时,A
为.
,因此您再次从A
遍历B
,这是不必要的。< / p>
这就是为什么递归永远不会结束,并且你得到了一个分段错误。
解决此问题的一种方法是保留一个单独的6x6阵列以跟踪访问点。当你完成一个单元格(即遍历来自该单元格的所有可能路径)时,将其标记为“已访问过”。一,并且再也不会访问被访问的小区。
答案 3 :(得分:0)
我在一张纸上写下你的迷宫并手动尝试了算法,然后卡在x = 2,y = 1,你的算法想要回到x = 1,y = 1,返回到之前的状态。该状态当然进入上述状态并产生无限循环。递归编程的一个重要规则是始终确保所有函数调用的所有执行路径都以返回调用(或类似)结束
如果你想对这个主题进行调整,我建议你研究shortest path problem使用例如Dijkstra's algorithm进行解决。