这是我对经典迷宫问题的解决方案。如果我只允许2次移动(向下或向右)并且只使用这2次移动就可以建立一条路径,那么它的工作非常完美。但是,如果我想允许所有4种可能的移动(向下,向右,向左,向上),程序永远不会给出解决方案(似乎递归堆栈最终增长并溢出)。我尝试使用小到4x4的迷宫,但没有成功。你能帮助我吗?
#
被屏蔽,.
免费。要增加允许的移动,请将#define MOVES (2)
增加或减少到#define MOVES (4)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ROW (10)
#define COL (10)
int start_index[]={0,0};
int end_index[]={9,9};
// char maze[R][C]={ // Can't solve this maze with 4 allowable moves
// {'.','#','.','.','.','.','.','.','.','.'},
// {'.','#','.','#','#','#','#','#','#','.'},
// {'.','#','.','#','#','#','#','#','#','.'},
// {'.','#','.','#','#','#','#','#','#','.'},
// {'.','#','.','#','#','#','#','#','#','.'},
// {'.','#','.','#','#','#','#','#','#','.'},
// {'.','#','.','#','#','#','#','#','#','.'},
// {'.','#','.','#','#','#','#','#','#','.'},
// {'.','#','.','#','#','#','#','#','#','.'},
// {'.','.','.','#','#','#','#','#','#','.'}
// };
char maze[ROW][COL]={ // Can solve this maze with 2 allowable moves
{'.','.','#','.','.','.','.','.','.','#'},
{'#','.','.','.','.','.','.','.','.','.'},
{'#','.','#','.','.','.','.','.','.','.'},
{'#','.','#','.','.','.','.','.','.','.'},
{'.','.','.','.','.','.','.','.','#','.'},
{'.','.','#','.','.','.','.','.','.','#'},
{'#','.','.','.','#','#','.','.','.','.'},
{'#','.','#','.','.','#','.','.','.','.'},
{'.','.','#','.','.','#','.','.','#','.'},
{'.','.','#','.','.','.','.','.','.','.'}
};
char sol[ROW][COL]={
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}
};
int move_x[]={0,1,0,-1};
int move_y[]={1,0,-1,0};
#define MOVES (4)
bool is_safe(int x,int y);
bool is_target(int x,int y);
bool solve_maze(int x,int y);
void print_mazes(bool solvable);
int main(){
printf("\nStarting");
bool solvable=solve_maze(start_index[0],start_index[1]);
print_mazes(solvable);
printf("\nEnd.");
}
bool solve_maze(int x,int y){
int next_x,next_y;
static int count=0;
bool tmp_res=false;
sol[x][y]='.';
printf("\n%d: (%d,%d)",count++,x,y);
for(int i=0;i<MOVES;i++){
next_x=x+move_x[i];
next_y=y+move_y[i];
if(is_safe(next_x,next_y)){
if(is_target(next_x,next_y)){
sol[next_x][next_y]='.';
return true;
}
else{
tmp_res=solve_maze(next_x,next_y);
if(tmp_res){
sol[next_x][next_y]='.';
return true;
}
else{
sol[next_x][next_y]='#';
}
}
}
}
return false;
}
bool is_safe(int x,int y){
if(x<COL && y<ROW && maze[x][y]!='#')
return true;
else return false;
}
bool is_target(int x,int y){
if(x==end_index[0] && y==end_index[1]) return true;
else return false;
}
// prints the original maze and the solution
void print_mazes(bool solvable){
printf("\n\n <<%sSolvable>>",(solvable)? "":"Not ");
printf("\n 0 1 2 3 4 5 6 7 8 9\t\t 0 1 2 3 4 5 6 7 8 9\n");
for(int i=0;i<ROW;i++){
printf("%d: ",i);
for(int j=0;j<COL;j++)
printf("%c ",maze[i][j]);
printf("\t\t%d: ",i);
for(int j=0;j<COL;j++)
printf("%c ",sol[i][j]);
printf("\n");
}
printf(" 0 1 2 3 4 5 6 7 8 9\t\t 0 1 2 3 4 5 6 7 8 9 \n");
}
答案 0 :(得分:2)
您应该在访问时尽快标记您访问过的单元格(而不是最后一次,就像使用sol[next_x][next_y]='#';
时那样。如果当前算法进入已经进入的单元格,则无法返回当前算法由堆栈下方的框架进入,导致某个无限循环(从而堆栈溢出)。
尝试在solve_maze
if (sol[x][y]=='#') return false;
做第一件事,sol[x][y] = '#';
,if (sol[x][y]=='#') return false;
。第一个声明:
sol[x][y] = '#';
说“如果此单元格已标记为已访问,请勿重新访问”。第二个声明:
'#'
表示“将此单元格标记为已访问”。或者,您可以使用'#'
以外的某些字符将单元格标记为已访问。我不确定这是否是你想要reject
表示的(似乎它意味着指示不在出口的某个路径上的细胞,但实际上在可解决的迷宫中,所有可探测的细胞都在某个路径上到出口)。