一、完整代码:
import util.*;
public class Main {
static boolean dfs(char[][] map, int y1, int x1, int y2, int x2) {
if(y1 == y2 && x1 == x2) return true;
char old = map[y1][x1];
map[y1][x1] = "*";
try {
if(y1 > 0 && map[y1-1][x1] == old && dfs(y1-1, x1, y2, x2)) return true;
if(y1 < map.length-1 && map[y1+1][x1] == old && dfs(y1+1, x1, y2, x2)) return true;
if(x1 > 0 && map[y1][x1-1] == old && dfs(y1, x1-1, y2, x2)) return true;
if(x1 < map.length-1 && map[y1][x1+1] && dfs(y1, x1+1, y2, x2)) return true;
}
finally {
map[y1][x2] = old;
}
return false;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
char[][] map = new char[n][];
for(int i = 0; i < n; i++) {
map[i] = cin.nextLine().toCharArray();
}
int m = cin.nextInt();
for(int i = 0; i < m; i++) {
String[] temp = cin.nextLine.split(" ");
int y1 = Integer.parseInt(temp[0]);
int x1 = Integer.parseInt(temp[1]);
int y2 = Integer.parseInt(temp[2]);
int x2 = Integer.parseInt(temp[3]);
boolean ans = dfs(y1, x1, y2, x2);
System.out.println(ans);
}
}
}
二、处理输入
1、对地图的处理
地图是这样输入的:
0010000000
0011100000
0000111110
0001100010
1111010010
0000010010
0000010011
0111111000
0000010000
0000000000
因为我们这里的输入比较紧密,没有被空格分隔,
所以可以利用String类中的toCharArray()方法,该方法可以自动将字符分割开来,还是挺好用的
char[][] map = new char[n][];
for(int i = 0; i < n; i++) {
map[i] = cin.nextLine().toCharArray();
}
2、对输入的起始位置的处理
每组输入是这样输入的:
0 0 9 9
0 2 6 8
4 4 4 6
这里就是很普通的切割被空格分割的字符串:
- 先用String类的split()方法,字符数组变得紧凑
- 然后强转成int
for(int i = 0; i < m; i++) {
String temp = cin.nextLine().split(" ");
int y1 = Integer.parseInt(temp[0]);
int x1 = Integer.parseInt(temp[1]);
int y2 = Integer.parseInt(temp[2]);
int x2 = Integer.parseInt(temp[3]);
boolean ans = dfs(map, y1, x1, y2, x2);
System.out.println(ans);
}
三、dfs
接下来是dfs,这里是boolean型的dfs,以前很少用到,可以值得好好解析一下。
1、递归出口
if(y1 == y2 && x1 == x2) return true;
如果一开始输入的起始位置相同,那么肯定可以搜索到。
更常见的情况是,随着下面的搜索循环体的dfs,(y1,x1)会不断移动,如果能够正好移动到(y2,x2),那就说明连通了。
2、dfs循环体
接下来,就是对上下左右四个方向进行dfs
比如向左方搜索:
if(y1 > 0 && map[y1][x1] == old && dfs(map, y1-1, x1, y2, x2)) return true;
这个和一般的dfs并没有什么不同,只不过是boolean型的
3、保护现场与恢复
char old = map[y1][x1]; //将起点的符号记录下来
map[y1][x1] = "*"; //标记为此时已经搜索过
try {
... //dfs循环体
}
finally {
map[y][x1] = old; //恢复现场
}
return false;
首先,我们需要判断的起始点对是很多组的,判断完毕一组之后,要将一切恢复到原来的样子,否则下一组怎么用呢?