【问题标题】:Recursion fails for Large N大 N 的递归失败
【发布时间】:2016-04-19 12:33:43
【问题描述】:

我遇到了这个问题。

让我们考虑一个游戏,它有一个 3 格宽、N 格高的棋盘。每个单元格都有一个 0 到 99 之间的数字写在上面。您可以在任何 顶行的单元格并从底部的任何单元格退出。你 可以从一个单元格移动到下一行中的任何相邻单元格(对角线或正下方)。 当你在一个单元格时,你必须加上或减去所写的数字 在细胞上。 对于给定值 X,大于或等于的最小数是多少 X,你可以从这个过程中获得?

输入 输入的第一行包含一个整数,数字 的测试用例。每个测试用例的第一行包含两个整数,NX。 接下来的 N 行每行包含三个 空格分隔的数字,必须添加或减去的单元格值。

输出

对于每组输入打印大于或等于的最小数 十。

示例输入

2
3 0
83 86 77
15 93 35
86 92 49
3 59
83 86 77
15 93 35
86 92 49

样本输出

2 59

注意:

2 = 86 - 35 - 49

59 = 86 - 93 + 86

这是我的解决方案:

import java.util.Scanner;

public class n3 {

    static int min;
    static int result;
    static int X;
    int go = 0;

    public static void main(String args[]) throws Exception {
        {
            Scanner sc = new Scanner(System.in);
            // sc = new Scanner(new FileInputStream("input.txt"));

            int T = sc.nextInt();
            for (int tc = 0; tc < T; tc++) {



                int N = sc.nextInt();
                min = sc.nextInt();

                result = Integer.MAX_VALUE;

                int m[][] = new int[N][N];
                for (int i = 0; i < N; i++) {
                    for (int j = 0; j < 3; j++) {
                        m[i][j] = sc.nextInt();
                    }
                }

                n3 game = new n3();
                game.start(m, N);
                System.out.println(result);

            }
        }
    }

    private void start(int[][] m, int N) {

        int x = min;
        compute(m, -1, 0, 0, N);
        // compute(m, -1, 0, -x, N);
        compute(m, -1, 1, 0, N);
        compute(m, -1, 2, 0, N);

    }

    private boolean isSafe(int[][] m, int row, int col, int N) {

        if (row >= 0 && col >= 0 && row < N && col < 3) {
            return true;
        }

        return false;
    }

    private void compute(int[][] m, int x, int y, int value, int N) {
        // System.out.println(value + " " + x + " " + y);

        if (go == 1) {
            return;
        }

        if (x == N - 1 && value >= min) {
            if (value < result) {
                result = value;
            }

            if (value == min) {
                result = min;
                go = 1;
            }
            return;
        }

        if (isSafe(m, x + 1, y - 1, N)) {
            compute(m, x + 1, y - 1, value + m[x + 1][y - 1], N);
            compute(m, x + 1, y - 1, value - m[x + 1][y - 1], N);
        }

        if (isSafe(m, x + 1, y, N)) {
            compute(m, x + 1, y, value + m[x + 1][y], N);
            compute(m, x + 1, y, value - m[x + 1][y], N);
        }

        if (isSafe(m, x + 1, y + 1, N)) {
            compute(m, x + 1, y + 1, value + m[x + 1][y + 1], N);
            compute(m, x + 1, y + 1, value - m[x + 1][y + 1], N);
        }

    }
}

但是,当 N 很大时,这会失败。有没有其他方法可以解决这个问题?

【问题讨论】:

  • 什么是 n 3 方板?
  • 当您描述这款游戏时,请考虑 (a) 我们不了解这款游戏,并且 (b) 我们无法读懂您的想法。
  • 失败怎么办?堆栈跟踪或您期望和接收的输出会很好。

标签: algorithm recursion dynamic-programming


【解决方案1】:

每次调用计算 (m, x, ...) 都会调用四次或六次计算 (m, x+1, ...)。因此,如果您将 N 增加 1,则工作至少会增加 4 倍。您的代码将永远运行。

对于每一行和每一列,跟踪您在该点可能拥有的整数集。然后在递归中,检查您是否已经计算了该行/列的点并且不要再这样做了。

【讨论】:

  • 你能举个例子吗?
【解决方案2】:

@gnasher729 有正确的想法。这是您给定示例的简短描述。

从棋盘顶部开始。对于每个方格,移动并计算每个方格的可能总数。将这些填写到列表列表中;这一行的“状态”类似于:

left:  [-83, 83],
mid:   [-86, 86],
right: [-77, 77]

现在移动到第 2 行。中间位置可以连接到 3 个方格中的每一个;两端只能连接到最近的 2. 对每个正方形应用加减运算。例如,左侧方格 (15) 可以通过左侧 (83) 或中间 (86) 位置“进给”。这一次,我将分两步解决:

left:  [-83-15, 83-15, -83+15, 83+15, -86-15, 86-15, -86+15, 86+15], 
mid:   [-83-93, 83-93, -83+93, 83+93, -86-93, 86-93, -86+93, 86+93, -77-93, 77-93, -77+93, 77+93]
right: [-86-35, 86-35, -86+35, 86+35, -77-35, 77-35, -77+35, 77+35]

当我们进行数学运算时,我们会得到条目:

[-98, 68, -68, 98, -101, 71, -71, 101],
[-176, -10, 10, 176, -179, -7, 7, 179, -170, -16, 16, 170],
[-121, 51, -51, 121, -112, 42, -42, 112]

继续沿着表格的行向下工作。由于您不关心路径,只关心总和本身,因此您不必跟踪所有小计 - 只需跟踪最近行的左侧、中间和右侧集合。

当你到达底部时,将三个列表合并,按升序排序,然后取第一个至少与 X 一样大的数字。

【讨论】:

    猜你喜欢
    • 2011-07-08
    • 2019-03-01
    • 2017-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    相关资源
    最近更新 更多