用Java打印递归迷宫解决方案

时间:2014-03-10 15:22:04

标签: java algorithm recursion printing

所以我一直在研究以下问题:

  

我埋了我的蓝宝石然后开始走路。我总是走进去   罗盘方向后的直线(N,S,E,W)。当我   停了下来,我转了90度并继续走路。我可能有   越过我的道路,但我不记得了。以下是米数   我走向各个方向。我现在迷路了,必须放弃这个   当我寻找出路时记录。我把这张便条放在了   摇滚在我的最后位置。也许一些幸运的冒险家会解码   我的笔记和回溯我的步骤来赚取宝藏。不幸,   没有关于废墟中发现纸币的记录。代替,   你必须写一个程序来寻找宝藏。输入第一个   line包含两个整数X Y,表示行数和   废墟中的列。最多20行50列。下一个X.   线条显示空间的网格图。句号“。”是空方格。一个   hash“#”是一块巨石,标志着一个无法进入的方块。   下一行有一个整数N,即直路径的计数   走着。最多20条路径。最后一行包含N个整数   用空格分隔,显示连续的路径长度.5 10

     ####      

........#

     

。#... ##。#

     

...#...#

     #### 8 2 4 2 2 2 5 2 1输出您的程序必须打印相同的地图,包括蓝宝石(S)和最终的位置      

标记的消息(F)的位置。此外,标记每个转折点   连续的小写字母(如果使用相同的点更多   不止一次,打印信件以便转弯。)只有一个   遵循列表中路径长度的路由。

     ####      

b.e.a..f#

     

。#... ##。#

     

c.d#S.Fg#

     #

我已经制作了一个递归方法,从迷宫的每个开放位置开始检查每个方向,直到找到解决方案,但问题的输出需要是转弯的迷宫。

问题是,当我使用递归解决方案并编辑实际的char [] []映射时,它永远不会知道哪条路径会导致实际完成,因此它将创建如下输出:

... d d

.....

cbabc

... d d

但我希望它只显示一条路径,如下所示:

... d

.....

.. ABC

.....

这是我不完整的解决方案:

import java.util.Scanner;

public class SapphireSearch {

    private static int rs; // Row Size
    private static int cs; // Column Size

    private static int sr; // Save row (saves solution row)
    private static int sc; // Save col (saves solution col)
    private static Direction sd; // Save direction (saves solution dir)

    private static char[][] map; // the maze to traverse

    private static int n; // number of turns

    private static int[] go; // length of the turns

    public static void main(String[] args) {
        getInput();
        for (int r = 0; r < rs; r++)
            for (int c = 0; c < cs; c++)
                for (Direction d : Direction.values())
                    solve(sr = r, sc = c, sd = d, 0, false);
    }

    public static void solve(int r, int c, Direction d, int start,
            boolean printing) {
        if (isSolid(r, c))
            return;
        if (printing) {
            if (start == 0)
                map[r][c] = 'S';
            else
                map[r][c] = (char) (start - 1 + 'a');
            if (start == n) {
                map[r][c] = 'F';
                return;
            }
        }
        if (start == n - 1 && !printing) {
            solve(sr, sc, sd, 0, true);
            printArray(map);
            System.exit(0);
        }
        int count = 0;
        while (start < go.length && count < go[start]) {
            count++;
            r += d.dr;
            c += d.dc;
            if (isSolid(r, c))
                return;
        }
        for (Direction t : d.turn())
            solve(r, c, t, start + 1, printing);
    }

    public static boolean isSolid(int r, int c) {
        return map[r][c] == '#';
    }

    public static void printArray(char[][] o) {
        for (int r = 0; r < o.length; r++) {
            for (int c = 0; c < o[r].length; c++)
                System.out.print(o[r][c]);
            System.out.println();
        }
    }

    private static void getInput() {
        Scanner s = new Scanner(System.in);
        rs = s.nextInt();
        cs = s.nextInt();
        s.nextLine(); // clear buffer
        map = new char[rs][cs];
        for (int r = 0; r < rs; r++) {
            int c = 0;
            char[] f = s.nextLine().trim().toCharArray();
            for (char t : f)
                map[r][c++] = t;
        }
        n = s.nextInt();
        go = new int[n];
        for (int i = 0; i < n; i++)
            go[i] = s.nextInt();
    }
}

enum Direction {
    // deltaR, deltaC
    up(-1, 0), down(1, 0), left(0, -1), right(0, 1);

    public int dr;
    public int dc;

    private Direction(int dr, int dc) {
        this.dr = dr;
        this.dc = dc;
    }

    public Direction[] turn() {
        Direction[] out = new Direction[2];
        switch (this) {
        case up:
        case down:
            out[0] = left;
            out[1] = right;
            break;
        case left:
        case right:
            out[0] = up;
            out[1] = down;
        }
        return out;
    }
}

问题是:在我的递归求解算法的基础上,打印解决方案路径的最佳方法是什么(它不会打印出它尝试采用的每个路径)?

1 个答案:

答案 0 :(得分:0)

你需要在进行递归搜索时建立你的转弯列表(我只是为了简单而列出这里的方向,但你也可以存储一个带有坐标的对象)。

如果路径为(N,E,N,W,S),则在退出时保存该路径。

要做到这一点,保留部分列表到目前为止,每次递归调用COPY到目前为止列表并添加到它。

即:

名词

NE nw失败

NEN nes失败

NENW

最后,您可以返回已完成的解决方案,或者如果您需要处理多个解决方案,则可以将完成的解决方案列入最终结果列表。

关键步骤是复制列表到目前为止,以便递归分支不会相互干扰。