蓝桥杯_连通性

一、完整代码:

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;

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

猜你喜欢

转载自www.cnblogs.com/huangming-zzz/p/10560389.html
今日推荐