题目:
从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;
}