题目分析
一道很典型的dfs模板题。 我们只要从起点出发进行深度优先搜索就行了,如若没有搜到终点那就是无喽
解题思路
很多大佬已经讲过了
我主要是想谈一下具体实现的小细节
1. 边界表示
本人采用给地图围一圈围墙('x')的方法来表示边界,也可以省去后续的一些判断,有x的地方不踩就行,边界、障碍物和访问过的地方都可以通过判断是否'x'的方式来决定踩不踩
//在地图外围包一层障碍物。可以省去出界的判断
for(int i = 0;i <= n+1;++i)
{
maze[i][0] = 'x';
maze[i][m+1] = 'x';
}
for(int i = 0;i <= m+1;++i )
{
maze[0][i] = 'x';
maze[n+1][i] = 'x';
}
2. 已访问节点的表示
看到很多大佬都是用了一个visited数组来记录走过的地方,我觉得可以直接放个路障'x'在上面,可以节省一个数组并化简后续判断
maze[x][y] = 'x';
效果:
//判断此路通不通
if(maze[X][Y] != 'x')
traverse(X,Y);
完整代码(递归版本)
因为本人比较菜,有时候看大牛的代码会有些脑子跟不上。我这里考虑到跟我一样的朋友们,我整理了代码,尽量用比较清晰的表示方式,并写了必要的注释,希望对新手朋友们有帮助
#include <iostream>
#include <algorithm>
using namespace std;
char maze[502][502];
int n,m;
//四个移动方向
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int startX,startY;
bool flag;
void traverse(int x,int y);;
int main(void)
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--)
{
cin >> n >> m;
flag = 0;
//在地图外围包一层障碍物。可以省去出界的判断
for(int i = 0;i <= n+1;++i)
{
maze[i][0] = 'x';
maze[i][m+1] = 'x';
}
for(int i = 0;i <= m+1;++i )
{
maze[0][i] = 'x';
maze[n+1][i] = 'x';
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
cin >> maze[i][j];
//记录起点位置
if(maze[i][j] == 's')
{
startX = i;
startY = j;
}
}
}
//开始遍历
traverse(startX,startY);
cout << (flag?"YES":"NO") << endl;
}
return 0;
}
void traverse(int x,int y)
{
maze[x][y] = 'x'; //已访问,放个路障,下次不要走了
int X,Y;
for(int i = 0;i < 4 && !flag;++i) //若flag=1说明已经找到,没再搜下去的必要,早点回家洗洗睡
{
//得到下一个要访问的坐标
X = x + dx[i];
Y = y + dy[i];
//判断是否到达终点
if(maze[X][Y] == 't')
flag = 1;
//判断此路通不通
if(maze[X][Y] != 'x')
traverse(X,Y);
}
}
踩坑:
之前马踏棋盘写魔怔了,本题我居然tm的回溯了(打自己
我们不需要具体路径,只需要知道起点终点是否连通
本题不用回溯也不可以回溯,回溯会超时,我甚至为此写了一版用栈,迭代模拟递归的代码,非常烂,但是也过了,贴下面,我就不整理了。
#include <iostream>
#include <stack>
#include <algorithm>
typedef long long ll;
using namespace std;
typedef struct _pos{
int x;
int y;
int i;
}pos;
char maze[510][510];
int n,m,flag;
stack<pos> s;
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int startX,startY;
void traverse(int x,int y);
void print(int n,int m);
int main(void)
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--)
{
flag = 0;
while(!s.empty())
s.pop();
cin >> n >> m;
for(int i = 0;i <= n+1;++i)
{
maze[i][0] = 'x';
maze[i][m+1] = 'x';
}
for(int i = 0;i <= m+1;++i )
{
maze[0][i] = 'x';
maze[n+1][i] = 'x';
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
cin >> maze[i][j];
if(maze[i][j] == 's')
{
startX = i;
startY = j;
}
}
}
// print(n,m);
pos t;
t.x = startX;
t.y = startY;
t.i = 0;
s.push(t);
traverse(startX,startY);
cout << (flag?"YES":"NO") << endl;
}
return 0;
}
void traverse(int xx,int yy)
{
pos t;
int x,X;
int y,Y;
int i;
while(!s.empty() && flag != 1)
{
// print(n,m);
// cout << endl;
pos top = s.top();
s.pop();
x = top.x;
y = top.y;
i = top.i;
maze[x][y] = 'x';
for(;i < 4;++i)
{
X = x+dx[i];
Y = y+dy[i];
if(maze[X][Y] == 't')
{
flag = 1;
return;
}
if(maze[X][Y] == '.')
{
top.i = i+1;
i=-1;
t.x = X;
t.y = Y;
t.i = 0;
s.push(top);
s.push(t);
break;
}
}
}
}
void print(int x,int y)
{
for(int i = 0;i <= x+1;++i)
{
for(int j = 0;j <= y+1;++j)
{
cout << maze[i][j] << ' ';
}
cout << endl;
}
}