递归头痛

时间:2015-07-01 13:06:34

标签: java arrays recursion

任务

鉴于包含整个非负数的2D数组m,我们将"路径" 定义为相邻单元格的集合(对角线步骤不算作邻居)从row == 0 && col == 0开始,以row == m.length - 1 && col == m[0].length - 1结束。

"路径的费用"是"路径"。

的每个单元格中的值的总和

示例:

数组中的两个可能路径: possible paths in an array

路径1(虚线)的成本:8 + 4 + 2 + 8 + 9 + 9 + 7 + 5 = 52;

路径2的成本(实线):8 + 6 + 3 + 8 + 9 + 4 + 1 + 2 + 1 + 7 + 6 + 5 = 60

要做:

编写一个static递归方法,接受一个填充了整个非负值的二维数组m,并输出所有可能路径成本的总和(您可以假设m不是null也不是空的。

方法签名是(允许重载):

public static void printPathWeights(int [][] m)

我的代码:

public class Main {

    public static void main(String[] args) {

        int arr[][] = { { 1, 1, 1 },
                        { 1, 1, 1 },
                        { 1, 1, 1 }
        };

        printPathWeights(arr);

    }

    public static void printPathWeights(int[][] m) {
        System.out.println(printPathWeights(m, 0, 0, new int[m.length][m[0].length], 0));
    }


    /*
     * @param map marks the visited cells
     */
    private static int printPathWeights(int[][] m, int row, int col, int[][] map, int carrier) {

        if (row < 0 || col < 0 || row >= m.length || col >= m[0].length || map[row][col] == 1)
            return 0;

        if (row == m.length - 1 && col == m[0].length - 1)
            return m[row][col] + carrier;

        map[row][col] = 1;
        return printPathWeights(m, row + 1, col, map, carrier + m[row][col]) +
                printPathWeights(m, row - 1, col, map, carrier + m[row][col]) +
                printPathWeights(m, row, col + 1, map, carrier + m[row][col]) +
                printPathWeights(m, row, col - 1, map, carrier + m[row][col]);

    }

}

上述代码的印刷值为:14

这比预期的少!

使用以下命令运行时

    int arr[][] = { { 1, 1 },
                    { 1, 1 }
    };

结果是预期的6。

我的代码有什么问题?

PS:请不要向我提供解决作业的代码,但要解释我的代码有什么问题。

3 个答案:

答案 0 :(得分:4)

代码标记一旦任意路径到达该单元格就访问的单元格。但是此细胞随后被标记为所有其他细胞的访问,并且不再被访问。这意味着该算法仅完成路径的子集,并且一些遍历在阵列中间的某处中断以获得更大的阵列。您必须将单元格标记为每条路径单独访问。

每次访问新单元格后,只需重置地图:

ULLONG_MAX

这将是最有效和最简单的方法。由于在访问单元格后复位了cellstate,因此它将永远不会从上一个路径中保留标记。

答案 1 :(得分:1)

正如Paul所说,您的代码所需的更改是在递归调用之后还原已访问的单元格集。它会按预期打印public class Main { public static void main(String[] args) { int arr[][] = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } }; printPathWeights(arr); } public static void printPathWeights(int[][] m) { System.out.println(printPathWeights(m, 0, 0, new int[m.length][m[0].length], 0)); } /* * @param map marks the visited cells */ private static int printPathWeights(int[][] m, int row, int col, int[][] map, int carrier) { if (row < 0 || col < 0 || row >= m.length || col >= m[0].length || map[row][col] == 1) return 0; if (row == m.length - 1 && col == m[0].length - 1) return m[row][col] + carrier; map[row][col] = 1; int result = printPathWeights(m, row + 1, col, map, carrier + m[row][col]) + printPathWeights(m, row - 1, col, map, carrier + m[row][col]) + printPathWeights(m, row, col + 1, map, carrier + m[row][col]) + printPathWeights(m, row, col - 1, map, carrier + m[row][col]); map[row][col] = 0; // Here return result; } }

<Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="98" Width="128"
            xmlns:local="clr-namespace:WpfApplication1">
    <Window.DataContext>
        <!-- This will auto create an instance of ViewModel -->
        <local:ViewModel /> 
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Label Name="lblTimer" Grid.Row="1" Content="{Binding Path=CurrentTime}"></Label>
    </Grid>
</Window>

答案 2 :(得分:0)

正如我所看到的那样,您只在一次递归中计算所有单元格的权重总和。但不考虑路径可能相交的事实,并且任何两条路径都可以有共同的单元格。就像图中所示的两条路径有共同的单元格并且必须添加两次