Arrays 阵列从左上角到右下角的路径数

Arrays 阵列从左上角到右下角的路径数,arrays,algorithm,perl,recursion,language-agnostic,Arrays,Algorithm,Perl,Recursion,Language Agnostic,我正在处理以下问题: 给定一个二维阵列,找到所有可能的方法从顶部移动 左单元格[0][0]到右下单元格[N-1][N-1],假设 只能向下或向右移动 我定义了以下内容: 对于像[[1]]这样的数组,从起始单元格到目标单元格只有一种方式。我们已经到了。 否则,总路径数是我们从单元格向右到目的地的总路径数加上1(从当前单元格到下一个单元格有1条路径)加上我们从下一个单元格到目的地的总路径数加上1(从当前单元格到下一个单元格有1条路径) 因此,对于以下数组: [ [1, 2] [3,

我正在处理以下问题:

给定一个二维阵列,找到所有可能的方法从顶部移动 左单元格
[0][0]
到右下单元格
[N-1][N-1]
,假设 只能向下或向右移动

我定义了以下内容:
对于像
[[1]]
这样的数组,从起始单元格到目标单元格只有一种方式。我们已经到了。
否则,总路径数是我们从单元格向右到目的地的总路径数加上1(从当前单元格到下一个单元格有1条路径)加上我们从下一个单元格到目的地的总路径数加上1(从当前单元格到下一个单元格有1条路径)
因此,对于以下数组:

[  
  [1, 2]  
  [3, 4]  
]  
[   
  [1, 2, 3],  
  [3, 4, 5],   
]  
答案是4(1->2,2->4,1->3,3->4)。
对于数组,例如:

[  
  [1, 2]  
  [3, 4]  
]  
[   
  [1, 2, 3],  
  [3, 4, 5],   
]  
答案应该是8。4来自右侧的子阵列+1,用于(1)->(2)加1->3->4->5总计3。
所以5+3=7。
下面的代码对我来说似乎是正确的,但我搞错了一些东西,得到了错误的结果

my $array = [
    [1, 2, 3],
    [3, 4, 5],
];

sub number_of_ways {
    my ( $input, $source_row, $source_col, $dest_row, $dest_col ) = @_;

    if ( $source_row == $dest_row && $source_col == $dest_col ) {
        return 1;
    }

    if ( $source_row >= scalar @$input) {
        return 0;
    }
    if ( $source_col >= scalar @{$input->[$source_row]} ) {
        return 0;
    }

    my $ways_down = number_of_ways($input, $source_row + 1, $source_col, $dest_row, $dest_col);
    my $ways_right = number_of_ways($input, $source_row, $source_col + 1, $dest_row, $dest_col); 
    my $total = $ways_right + 1 if ( $ways_right );
    $total += $ways_down + 1 if ( $ways_down );
    return $total;
}

print "Number of ways: " . number_of_ways($array, 0, 0, 1, 2). "\n";  
这给我11英镑。
逻辑错了吗

更新:
在@m69的帮助下,我找到了问题。
在递归中,如果我们已经可以检查迭代是否会失败,那么进行迭代是一个坏主意。在这种情况下,即使在@m69注释后更改代码,它也会失败,因为0之间没有区别,因为我们在一个包含1个元素的子数组中(源和目标相同),或者在数组之外。
下面的代码似乎是正确的

sub number_of_ways {
    my ( $input, $source_row, $source_col, $dest_row, $dest_col ) = @_;

    if ( $source_row == $dest_row && $source_col == $dest_col ) {
        return 0;
    }

    my $total = 0;
    if ( $source_row < @$input - 1) {
        my $ways_down = number_of_ways($input, $source_row + 1, $source_col, $dest_row, $dest_col);
        $total += $ways_down + 1;
    }
    if ( $source_col < @{$input->[$source_row]} - 1 ) {
        my $ways_right = number_of_ways($input, $source_row, $source_col + 1, $dest_row, $dest_col); 
        $total += $ways_right + 1;
    }

    return $total;
}

print "Number of ways: " . number_of_ways($array, 0, 0, 1, 2). "\n";
路径的子编号{
我的($input、$source\u row、$source\u col、$dest\u row、$dest\u col)=@;
if($source\u row==$dest\u row&$source\u col==$dest\u col){
返回0;
}
我的$total=0;
如果($source_row<@$input-1){
my$ways\u down=路径数($input、$source\u row+1、$source\u col、$dest\u row、$dest\u col);
$total+=$ways\u down+1;
}
如果($source\u col<@{$input->[$source\u row]}-1){
我的$ways\u right=路径数($input、$source\u row、$source\u col+1、$dest\u row、$dest\u col);
$total+=$ways\u right+1;
}
返回$total;
}
打印“方式数:”。方法的数量($array,0,0,1,2)。“\n”;

您的算法使用此递归:

01120---120
=               +   |
3   4   5           4   5       3   4   5
接着是:

1 2 1---2 1
=+|和
4   5           5       4   5         3   4   5   =   3---4   5
然后:

2
=|和
5       5         4   5   =   4---5         4   5   =   4---5
最后:

5和5以及5
就其本身而言,这是在3x2网格中递归的一种有用方法,但随后添加步骤的方式是有问题的;e、 g.在接收到2x2网格[[1,2][4,5]]递归的结果4后,您向其添加1,因为从位置0到2x2网格需要1步。但是,2x2网格中有两条路径,因此您应该添加两次1步骤。要知道通过2x2网格有多少条路径,需要计算通过该网格的出租车距离,然后将步数除以该距离。您将看到,这会导致大量不必要的计算,因为每个完整路径中的步数总是相同的。因此,只需找到路径数,然后将它们乘以每条路径的步数,就容易多了

您可以使用递归查找路径数;从上面递归的分解步骤中,您将看到最终使用1x1网格[5]三次。这是因为有三条路径通向位置5。如果您只需计算使用1x1网格递归的次数),就可以知道路径的数量。要知道步数,您可以乘以(宽度-1)+(高度-1),这是每条路径中的步数

在递归范围之外简单地递增变量的缺点是,您无法轻松地将其转换为动态编程解决方案,因为您必须将每个递归进行到底,以计算到达右下角的次数。因此,最好将结果传递回递归链

如果在输入为1x1网格时返回1,并且右和下的总和将产生一个更大的网格(不向其添加任何内容),则这也将给出路径总数。然后,您可以通过存储2x1和1x2网格返回1、2x2网格返回2、3x2和2x3网格返回3、3x3网格返回6来记忆结果,并使用这些存储的值,而不是再次在相同大小的网格上递归

您将看到,通过任意大小网格的路径数如下表所示:

1  1  1  1  1 ...
1  2  3  4  5
1  3  6 10 15
1  4 10 20 35
1  5 15 35 70
其中,每个值都是上面和左边的值之和,这也指向一种简单的非递归方法来计算通过任意大小网格的路径数(或步数)


JavaScript中的此代码段使用代码中的递归方法计算路径数,然后计算步骤总数:

函数计数路径(网格、x、y){
x=x | | 0;y=y | | 0;
变量高度=网格长度-y;
变量宽度=网格[0]。长度-x;
如果(宽度==0 | |高度==0)返回0;
如果(宽度==1和高度==1)返回1;
返回count_路径(网格,x+1,y)+count_路径(网格,x,y+1);
}
var网格=[[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15];
var路径=计数路径(网格);
var steps=path*(grid.length-1+grid[0].length-1);

文档。写入(“路径:“+path+”
步骤:“+steps”)你能给我解释一下如何进行arr吗