DFS破解“迷宫问题”(洛谷P1605题题解,Java语言描述)

迷宫

迷失方向越挣扎越疯狂~
好像落入巨网~~
进退两难越想抵达越彷徨~
如同卷入旋涡~~

在这里插入图片描述

每个人都会有自己的“迷宫”,也希望大家从中都能走出来,通向更光明的未来!

题目要求

P1605题目链接
在这里插入图片描述

分析

我的思路还比较容易理解,但确实开的数组太多了(最终代码)。
我想开一个递归的DFS搜索,对越界情况进行淘汰 (话说这能算剪枝吗) ,再就是只允许在没被标记为已遍历的地方行进。
DFS用好了确实能搜出结果,但过程中遇到过一个大问题,下面就对此说明。

原先的代码是这样的:

import java.util.Scanner;

public class Main {

    private static int x1, y1, x2, y2;

    private static int dfs(int x, int y, boolean[][] graph) {
        if (x < x1 || x > x2 || y < y1 || y > y2 || graph[x][y]) {
            return 0;
        } else if (x == x2 && y == y2) {
            return 1;
        }
        graph[x][y] = true;
        return dfs(x-1, y, graph) + dfs(x+1, y, graph) + dfs(x, y-1, graph) + dfs(x, y+1, graph);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int m = scanner.nextInt(), n = scanner.nextInt(), num = scanner.nextInt();
        x1 = scanner.nextInt();
        y1 = scanner.nextInt();
        x2 = scanner.nextInt();
        y2 = scanner.nextInt();
        boolean[][] graph = new boolean[m+1][n+1];
        for (int i = 0; i < num; i++) {
            graph[scanner.nextInt()][scanner.nextInt()] = true;
        }
        scanner.close();
        System.out.println(dfs(x1, y1, graph));
    }
    
}

获取了测试数据2:
in

5 5 5 
1 2 5 5
2 1
2 2
2 3
2 4
3 4

out

10

自己在纸上推演了一段时间,发现是由于这个数据挺刁钻(其实不过分啊),卡住了一个口子,所以我的程序就走不进去了。本质上的错误是:忽略了Java数组传引用这个事情。
之前,我写过一篇博客:《探究Java方法的参数传递是值传递还是引用传递》。我承认,里面有的结论我也不是100%确定,但确实也是被这个题逼得没办法。

正因为传的是引用,至少也说明可以改引用,所以我们就很难处理了:一次的遍历就可能“堵上道路”,让其他的递归情况没法进行。
事实上,我们要想递归的同时还开深拷贝的专属标记数组,成本是很高的。

但我也没别打法子,看了看测试范围,很小,那就咬咬牙开数组copy吧(当时对数组拷贝的策略领会的不是很好,可以看这篇文章——《总结Java数组的拷贝和输出》)。

扫描二维码关注公众号,回复: 9811612 查看本文章

当然了,其实在这种小数组范围内,直接复制很简单也很方便。

AC代码(Java语言描述)

import java.util.Scanner;

public class Main {

    private static int x2, y2, m, n;

    private static int dfs(int x, int y, boolean[][] graph) {
        if (x < 1 || x > m || y < 1 || y > n || graph[x][y]) {
            return 0;
        } else if (x == x2 && y == y2) {
            return 1;
        }
        graph[x][y] = true;
        boolean[][] array1 = new boolean[m+1][n+1];
        boolean[][] array2 = new boolean[m+1][n+1];
        boolean[][] array3 = new boolean[m+1][n+1];
        boolean[][] array4 = new boolean[m+1][n+1];
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                array1[i][j] = graph[i][j];
                array2[i][j] = graph[i][j];
                array3[i][j] = graph[i][j];
                array4[i][j] = graph[i][j];
            }
        }
        return dfs(x-1, y, array1) + dfs(x+1, y, array2) + dfs(x, y-1, array3) + dfs(x, y+1, array4);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        m = scanner.nextInt();
        n = scanner.nextInt();
        int num = scanner.nextInt();
        int x1 = scanner.nextInt();
        int y1 = scanner.nextInt();
        x2 = scanner.nextInt();
        y2 = scanner.nextInt();
        boolean[][] graph = new boolean[m+1][n+1];
        for (int i = 0; i < num; i++) {
            graph[scanner.nextInt()][scanner.nextInt()] = true;
        }
        scanner.close();
        System.out.println(dfs(x1, y1, graph));
    }

}
发布了691 篇原创文章 · 获赞 1478 · 访问量 67万+

猜你喜欢

转载自blog.csdn.net/weixin_43896318/article/details/104831808