## [$AcWing$ $1112$. 迷宫](https://www.acwing.com/problem/content/1114/) ### 一、题目描述 一天$Extense$在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由 $n∗n$ 的格点组成,每个格点只有$2$种状态,`.`和`#`,前者表示 **可以通行** 后者表示 **不能通行**。 同时当$Extense$处在某个格点时,他只能移动到东南西北(或者说**上下左右**)四个方向之一的相邻格点上,$Extense$想要从点$A$走到点$B$,问在不走出迷宫的情况下能不能办到。 如果起点或者终点有一个不能通行(为`#`),则看成无法办到。 **注意**:$A、B$不一定是两个不同的点。 **输入格式** 第$1$行是测试数据的组数 $k$,后面跟着 $k$ 组输入。 每组测试数据的第1行是一个正整数 $n$,表示迷宫的规模是 $n∗n$ 的。 接下来是一个 $n∗n$ 的矩阵,矩阵中的元素为`.`或者`#`。 再接下来一行是 $4$ 个整数 $h_a,l_a,h_b,l_b$,描述 $A$ 处在第 $h_a$ 行, 第 $l_a$ 列,$B$ 处在第 $h_b$ 行, 第 $l_b$ 列。 注意到 $h_a,l_a,h_b,l_b$ 全部是从 $0$ 开始计数的。 **输出格式** $k$行,每行输出对应一个输入。 能办到则输出`YES`,否则输出`NO`。 **数据范围** $1≤n≤100$ **输入样例**: ```cpp {.line-numbers} 2 3 .## ..# #.. 0 0 2 2 5 ..... ###.# ..#.. ###.. ...#. 0 0 4 0 ``` **输出样例**: ```cpp {.line-numbers} YES NO ``` ### 二、$dfs$ ```cpp {.line-numbers} #include using namespace std; const int INF = 0x3f3f3f3f; // dfs只能求出来是否连通,第一次搜索到时并不能保证是最短距离 // bfs也可以做,可以保证第一次到达时是最短距离 // dfs好处是代码短,按时间排名,那么先AC的同学排名靠前 // 用标记数组进行标记,每个位置只使用一次,性能N*N const int N = 110; int n; char g[N][N]; // 地图 int xa, ya, xb, yb; int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; bool st[N][N]; // 是否走过 bool flag; void dfs(int x, int y) { if (x == xb && y == yb) { flag = true; return; } for (int i = 0; i < 4; i++) { int tx = x + dx[i], ty = y + dy[i]; if (tx < 0 || tx == n || ty < 0 || ty == n) continue; if (st[tx][ty]) continue; if (g[tx][ty] == '#') continue; st[tx][ty] = true; dfs(tx, ty); } } int main() { int T; cin >> T; while (T--) { cin >> n; for (int i = 0; i < n; i++) cin >> g[i]; cin >> xa >> ya >> xb >> yb; // 多组测试数组,每次初始化0 memset(st, 0, sizeof st); flag = false; // 这小坑坑挺多啊 if (g[xa][ya] == '#' || g[xb][yb] == '#') { puts("NO"); continue; } st[xa][ya] = true; dfs(xa, ya); if (flag) puts("YES"); else puts("NO"); } return 0; } ``` ### 三、$bfs$ ```cpp {.line-numbers} #include using namespace std; struct Node { int x; int y; int step; }; const int N = 110; int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; char g[N][N]; bool st[N][N]; int n; int xa, ya, xb, yb; // 不能使用x1,y1这样的变量名,可能是万能头中有重复声明 bool flag; void bfs() { flag = false; if (g[xa][ya] == '#') return; if (g[xb][yb] == '#') return; memset(st, 0, sizeof st); if (xa == xb && ya == yb) { flag = true; return; } queue q; q.push({xa, ya, 0}); st[xa][ya] = true; while (q.size()) { auto t = q.front(); q.pop(); for (int i = 0; i < 4; i++) { int x = t.x + dx[i], y = t.y + dy[i]; if (x < 0 || x >= n || y < 0 || y >= n) continue; if (st[x][y]) continue; if (g[x][y] == '#') continue; if (x == xb && y == yb) { flag = true; return; } q.push({x, y, t.step + 1}); st[x][y] = true; } } } int main() { int T; cin >> T; while (T--) { cin >> n; for (int i = 0; i < n; i++) cin >> g[i]; cin >> xa >> ya >> xb >> yb; bfs(); if (flag) cout << "YES" << endl; else cout << "NO" << endl; } return 0; } ```