蓝桥杯_连通性

一、完整代码:

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

这里就是很普通的切割被空格分割的字符串:

  1. 先用String类的split()方法,字符数组变得紧凑
  2. 然后强转成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;

首先,我们需要判断的起始点对是很多组的,判断完毕一组之后,要将一切恢复到原来的样子,否则下一组怎么用呢?

posted @ 2019-03-19 18:13  明卿册  阅读(283)  评论(0编辑  收藏  举报