题目:
从s到t,.
意味着可以走,*
意味着不能走,如果能走,输出路径,如果不能走,输出no
。
输入:
5 6
....S*
.***..
.*..*.
*.***.
.T....
输出:
....m*
.***mm
.*..*m
*.***m
.Tmmmm
分析与解答
1.整体思路:
我们先从第一个走的,因此先把第一个格子标记为已走过,然后开始走第一个格子上下左右的相邻格子,如果这个相邻格子没走过,而且从这个相邻格子能走到下一个格子,那么就可以一直走下去,继续调用dfs。
当调用dfs直到无法走下一个格子,这时直接返回false,然后回到上一个格子,直到返回到最开始的那个格子,此时最开始的格子走另一个方向的格子。然后继续重复之前的调用,直到找到终点。
2.推广到dfs的研究方法:
1.处理搜索结束时的边界条件
2.搜索:我们判断是否能继续往下搜,需要满足下一个方向的坐标在地图里面,而且没有被走过,而且没遇到墙。如果满足这些条件,就再调用dfs,继续往下搜。
3.回溯:当所有方向都搜完,也没找到路径,此时函数运行结束,这一层返回false,返回上一层的递归。返回之前,我们需要把访问时做的标记还原。返回上一层有可能就是改变方向继续进行新的搜索,直到达到边界条件。
如果说最后到了边界条件,那么底层的返回true,然后依次往上全部返回true,这样dfs(x,y)就返回true。就说明从起始点xy走是可以到终点的。
如果说一直都没有到边界条件,那么也就是说我们一开始把起始点设定为已经走过的点,然后上下左右搜索最后全部都回来了,此时第一层中那几个if都用完了,于是就继续往下走,也就是说,把起始的那个格子给初始化,并且返回false。
3.代码的简洁性:
然后由四个方向搜索,我们可以发现它有四个一摸一样的if,只不过每次的x和y的值有所不同,那么我们就可以引入一个方向变量,int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}}; 这样的话,我们就可以通过for循环和方向变量实现每次对xy的值的修改,然后再把if写道for里面,这样就不用把四个方向分开写了,简化了代码量。
代码
#include <iostream>
#include <string>
using namespace std;
int n, m;
string maze[110];
bool vis[110][110];
bool in(int x,int y){//防止走到地图外面return 0<=x&&x<n&&0<=y&&y<m;
}
bool dfs(int x,int y){//x代表行,y代表列if(maze[x][y]=='T'){return true;}vis[x][y]=1;//标记当前点已走过maze[x][y]='m';//走过的点用字符m标记int tx = x-1,ty=y;//向上搜if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){if(dfs(tx,ty)){return true;}}tx=x,ty=y-1;//左if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){if(dfs(tx,ty)){return true;}}tx=x+1,ty=y;//下if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){if(dfs(tx,ty)){return true;}}tx=x,ty=y+1;//右if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){if(dfs(tx,ty)){return true;}}vis[x][y]=0;maze[x][y]='.';return false;
}
int main() {// 输入迷宫地图cin >> n >> m;for (int i = 0; i < n; i++) {cin >> maze[i];}int x,y;//确定起始位置for(int i=0;i<n;++i){for(int j=0;j<m;++j){if(maze[i][j]=='S'){x=i,y=j;}}}if(dfs(x,y)){for(int i=0;i<n;++i){cout<<maze[i]<<endl;}}else{cout<<"NO!"<<endl;}return 0;
}
用二维数组将上下左右搜索整合到一个for循环里。
#include <iostream>
#include <string>
using namespace std;
int n, m;
string maze[110];
bool vis[110][110];
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
bool in(int x, int y) {return 0 <= x && x < n && 0 <= y && y < m;
}
bool dfs(int x, int y) {if(maze[x][y] == 'T'){return true;}vis[x][y]=1;maze[x][y]='m';for(int i=0;i<4;++i){int tx=x+dir[i][0];int ty=y+dir[i][1];if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){if(dfs(tx,ty)){return true;}}}vis[x][y]=0;maze[x][y]='.';return false;
}
int main() {cin >> n >> m;for (int i = 0; i < n; i++) {cin >> maze[i];}int x, y;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (maze[i][j] == 'S') {x = i, y = j;}}}if (dfs(x, y)) {for (int i = 0; i < n; i++) {cout << maze[i] << endl;}} else {cout << "NO!" << endl;}return 0;
}