using System;
using System.Collections.Generic;
using System.Linq;
public class Program {
public static void Main() {
int[] inputs = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
int n = inputs[0];
int m = inputs[1];
List<List<char>> maze = new List<List<char>>();
for (int i = 0; i < n; i++) {
maze.Add(Console.ReadLine().ToCharArray().ToList());
}
bool[,] visited = new bool[n, m]; //用来储存哪些格子已经被走过了
Random random = new Random();
int randomInRange = random.Next(-10, 11);
//随机调用两种DFS方法
if (randomInRange >= 0) {
Console.WriteLine(DFSMazeRecusive(maze, visited, 0, 0, n, m));
} else {
Console.WriteLine(DFSMazeNotRecusive(maze, visited, 0, 0, n, m));
}
}
//DFS迷宫寻路,递归写法,左上角(1,1)为起点,右下角(n,m)为终点。变量迷宫maze和Visted数组还有r,c,n,m都不用作为全局变量定义在类变量中,只需要在每次递归的时候作为参数重新传给DFS函数即可
public static string DFSMazeRecusive(List<List<char>> maze, bool[,] visited,
int r,
int c, int n, int m) {
//到达终点的条件
if (r == n - 1 && c == m - 1) {
return "Yes";
}
//当前走的格子设置为True
visited[r, c] = true;
//没有到达终点,则向四个方向走,上下左右
int[] directionR = {-1, 1, 0, 0 };
int[] directionC = {0, 0, -1, 1 };
//遍历四种走的方向,看哪个方向是可以走的
for (int i = 0; i < 4; i++) {
int nextR = r + directionR[i];
int nextC = c + directionC[i];
//判断下个方向可不可以走的条件是,不能超过迷宫边界(nextR >= 0 && nextC >= 0 && nextR < n && nextC < m),下个方向上的格子是'.'(maze[nextR][nextC] == '.'),且没有被走过(!visited[nextR, nextC])
if (nextR >= 0 && nextC >= 0 && nextR < n && nextC < m &&
maze[nextR][nextC] == '.' && !visited[nextR, nextC]) {
if (DFSMazeRecusive(maze, visited, nextR, nextC, n, m) == "Yes")
return "Yes";//递归
}
}
//如果到达终点的条件和向下一个格子走的条件没有触发,说明这个迷宫走不到终点,返回NO
return "No";
}
//非递归写法,用stack,这里的bool[,] visited, int r, int c, int n, int m传入参数其实都是不必要的,但是懒得改了
public static string DFSMazeNotRecusive(List<List<char>> maze, bool[,] visited,
int r, int c, int n, int m) {
Stack<int[]> stack = new
Stack<int[]>();//非递归法要用Stack来装下一个走到的格子,模拟系统的调用栈
visited[0, 0] =
true; //visited数组用来记录哪些格子走过了,防止重复入栈
int[] ori = {0, 0};
stack.Push(ori);//起点入栈
//定义四种方向
int[] directionR = { -1, 1, 0, 0 };
int[] directionC = { 0, 0, -1, 1 };
while (stack.Count >
0) { //若stack长度为0了,说明在走到终点之前就没有可走的格子了,说明终点不可达
//出栈,走到当前位置,如果一直出栈就说明当前道路往上下左右都走不通,要一直往回走
int[] coor = stack.Pop();
int row = coor[0];
int col = coor[1];
if (row == n - 1 && col == m - 1) //到达终点
return "Yes";
for (int i = 0; i < 4; i++) {
int nextR = row + directionR[i];
int nextC = col + directionC[i];
//依旧是判断下一个格子能不能走
if (nextR >= 0 && nextC >= 0 && nextR < n && nextC < m &&
maze[nextR][nextC] == '.' && !visited[nextR, nextC]) {
visited[nextR, nextC] = true;
int[] nextCoor = { nextR, nextC };
stack.Push(nextCoor);//入栈
}
}
}
return "No";
}
}