今天的题目是一道小虫子逃迷宫的题
我们先来读读题。
----------
由于新冠肺炎疫情的爆发,小明养在宿舍的小昆虫已经很久很久都没有人管了。小昆虫已经饿的不行了,
必须出来找东西吃,可是出来之后需要走出一个迷宫。小昆虫每次可以朝上、下、左、右四个方向之一走步,
且只要走出任意一条边界线即可逃出迷宫。这只小昆虫曾感染过X星的一种奇异病毒,目前还没有发现任何副作用,
但是却拥有了一项特异功能—破坏障碍物。
假设小昆虫在一个 N*M 的迷宫中,① "@"代表小昆虫的初始位置,② "."代表可以通过的空地,
③"*"代表可以破坏的障碍物,④"#代表不可破坏的障碍物。请问小昆虫最少需要使用多少次特异功能才可以逃出迷宫?
输入描述
多组数据,第1行有1个正整数T,表示有T组数据。 (T<=100)
对于每组数据,第1行有两个整数N和M。(1<=N, M<=1000)
接着N行,每行有一个长度为M的字符串,表示N*M的迷宫。
输出描述
Plain Text
输出一个整数,表示使用特异功能的最少次数。如果小昆虫不能走出迷宫,则输出-1.
--------》
样例输入 :
3
3 3
###
#@*
***
3 4
####
#@.*
**.*
3 3
.#.
#@#
.#.
--------》
样例输出 :
1
0
-1
读完题,当时没感觉到啥,但一看到输入输出,咦,又是一个二维的字符数组,根据题意可以得出本题的意思是在二维数组中判断从@开始,到跳出二维数组,有多少种方法,然后从这些方法中找出使用 “ . ” 最少的那个呀,所以这个题我们还是需要用深度优先搜索来做。
老规矩,判断完是使用搜索来做之后,我们就来找递归三要素。
一,函数设计
遇到在二维数组中找符合条件的个数的问题,就先把 行和列 写上,然后在给一个变量记录每一种方法中,使用特异功能的次数 。
public void dfs(int i, int j, int count)
二,终止条件
跳出二维数组就是需要终止啦。
if (i < 0 || j < 0 || i >= row || j >= col) {
res = Math.min(res, count); // 求出每一次跳出循环时,当前最少的 ‘.’的个数
return;
}
三,递归方向
在二维数组中找东西,方向有且只有上下左右四个方向,难不成还要斜着找嘛(有的变态题可能还真有!)
dfs(i + 1, j, count);
dfs(i, j + 1, count);
dfs(i - 1, j, count);
dfs(i, j - 1, count);
代码贴出来:
在这里插入代码片
public int getInsect(char[][] chars , int N , int M , int startI , int startJ) {
N = row;
M = col;
this.visited = new boolean[N][M] ;
this.res = Integer.MAX_VALUE ;
dfs(startI,startJ,0);
return res == Integer.MAX_VALUE ? -1 : res ;
}
char[][] c ;
int row , col ;
int res ;
boolean[][] visited ;
public void dfs(int i , int j , int count) {
if (i<0||j<0||i>row||j>=col) {
// 将当前的跳出是.的个数与上一个相比,这样可以得出最后得到的值是最少的
res = Math.min(res,count) ;
return;
}
if (visited[i][j] = true) return; // 染色,保证每一次走过的路都不会再走
visited[i][j] = true ;
if (c[i][j] == '#') return;
if (c[i][j] == '*') count++ ;
dfs(i+1,j,count);//右
dfs(i-1,j,count);//左
dfs(i,j+1,count);//上
dfs(i,j-1,count);//下
visited[i][j] = false; //回溯操作 清除刚才的记录 防止下一次函数被调用时结果收到上一条影响
}
写完了 ,我们来写个main方法来测试下。
在这里插入代码片
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int T = scanner.nextInt();
while (T > 0) { // 表示T组数据
int N, M, starti = 0, startj = 0;
N = scanner.nextInt(); // M行
M = scanner.nextInt(); // N列
scanner.nextLine(); //这个表示可以读取空格 表示我们要换行输入啦~
char[][] map = new char[N][M];
for (int i = 0; i < N; i++) {
char[] tmp = scanner.nextLine().toCharArray(); //每一行都是一个一维数组
for (int j = 0; j < M; j++) {
map[i][j] = tmp[j];
if (tmp[j] == '@') { //找到起始点 然后递归哦
starti = i;
startj = j;
}
}
}
System.out.println(new insect().solution(map, N, M, starti, startj));
T--;
}
}
测试结果如下:
搞定!
2020年11月24日18:37:55