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吗