Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 计算二维阵列上的路径数(栅格移动器)_Arrays_C_Algorithm_Recursion_Dynamic Programming - Fatal编程技术网

Arrays 计算二维阵列上的路径数(栅格移动器)

Arrays 计算二维阵列上的路径数(栅格移动器),arrays,c,algorithm,recursion,dynamic-programming,Arrays,C,Algorithm,Recursion,Dynamic Programming,我有以下目标:“给定二维m×n矩阵,写一个算法来计算从左上角到右下角的所有可能路径。你只能向两个方向移动,向右移动或向下移动。” 这个问题很容易解决。例如,3 x 3栅格的路径数等于2 x 3栅格和3 x 2栅格的总和。因此,递归解决方案非常直观 我实现了一个递归解决方案和一个带记忆的解决方案(其中2d数组存储已经计算的路径)。在C语言中,但不知何故,当网格变得太大时,两个函数仍然返回相同的负解(即15 x 15很好,18 x 18,不再是)。知道这是从哪里来的吗?我的代码附在下面。 也。。有没

我有以下目标:“给定二维m×n矩阵,写一个算法来计算从左上角到右下角的所有可能路径。你只能向两个方向移动,向右移动或向下移动。” 这个问题很容易解决。例如,3 x 3栅格的路径数等于2 x 3栅格和3 x 2栅格的总和。因此,递归解决方案非常直观

我实现了一个递归解决方案和一个带记忆的解决方案(其中2d数组存储已经计算的路径)。在C语言中,但不知何故,当网格变得太大时,两个函数仍然返回相同的负解(即15 x 15很好,18 x 18,不再是)。知道这是从哪里来的吗?我的代码附在下面。 也。。有没有一种很好的方法来编码备忘录解决方案的数组?如果我使用
A[m][n]
作为函数参数,它不太管用,所以我只是暂时硬编码它

谢谢

#include <stdio.h>

int gridTravel(int m, int n){
    if (m == 0 || n == 0){
        return 0;
    }
    if (m == 1 || n == 1){
        return 1;
    }
    return gridTravel(m-1, n) + gridTravel(m, n-1);
}

int gridTravelMemo(int m, int n, int A[15][15]){
    if (m == 0 || n == 0){
        return 0;
    }
    if (m == 1 || n == 1){
        return 1;
    }
    if (A[m-1-1][n-1] == 0){
        A[m-1-1][n-1] = gridTravelMemo(m-1, n, A);
    }
    if (A[m-1][n-1-1] == 0){
        A[m-1][n-1-1] = gridTravelMemo(m, n-1, A);
    }
    return  A[m-1-1][n-1] + A[m-1][n-1-1];
}

int main(){
    int res = gridTravel(15,15);
    printf("There is a total of %d ways to traverse the grid (Grid size is 15 by 15).\n", res);

    int res2 = gridTravel(18,18);
    printf("There is a total of %d ways to traverse the grid (Grid size is 18 by 18).\n", res2);
    
    int A[15][15] = {0};
    int res_memo = gridTravelMemo(15,15,A);
    printf("There is a total of %d ways to traverse the grid (Grid size is 15 by 15).\n", res_memo);

    return 0;
}

#包括
整数网格旅行(整数m,整数n){
如果(m==0 | | n==0){
返回0;
}
如果(m==1 | | n==1){
返回1;
}
返回网格行程(m-1,n)+网格行程(m,n-1);
}
int gridTravelMemo(int m、int n、int A[15][15]){
如果(m==0 | | n==0){
返回0;
}
如果(m==1 | | n==1){
返回1;
}
如果(A[m-1-1][n-1]==0){
A[m-1-1][n-1]=gridTravelMemo(m-1,n,A);
}
如果(A[m-1][n-1-1]==0){
A[m-1][n-1-1]=gridTravelMemo(m,n-1,A);
}
返回[m-1-1][n-1]+A[m-1][n-1-1];
}
int main(){
int res=网格旅行(15,15);
printf(“总共有%d种方式穿过网格(网格大小为15 x 15)。\n”,res);
int res2=网格旅行(18,18);
printf(“总共有%d种方式穿过网格(网格大小为18×18)。\n”,res2);
int A[15][15]={0};
int res_memo=gridTravelMemo(15,15,A);
printf(“总共有%d种方式穿过网格(网格大小为15×15)。\n”,res_memo);
返回0;
}

对res和res1使用长变量类型代替int类型


递归查找超出了int限制。

我不会在这里使用任何动态编程或递归,而是使用组合数学来解决它

正如@Eric Postpischil所指出的,在计算路径数时,您应该使用更宽的类型,如
uint64\t
无符号long
或类似类型

解释 你要问的是,长度为
m-1+n-1
的路径如何从左上角点开始,到右下角点结束。为什么
m+n-2

因为你只能向右或向下移动。最初,您是距离目标
m-1
行和
n-1
列。每一步,您都会使
1
行或
1
列更接近目标。因此,您需要准确地执行
m+n-2
步骤

但是有多少种组合呢?在
m+n-2
步骤中,您必须准确地执行
m-1
向下和
n-1
向右的步骤。因此,从
m+n-2
步数中选择
m-1
垂直步数(或
n-1
水平步数)的方法有Cm-1m+n-2或Cn-1m+n-2(如果需要,请查看此处的定义)

公式 以下两个公式产生相同的结果

Cm-1m+n-2

Cn-1m+n-2

代码 然后,您的方法可以如下重新实现。请注意,如果
n
m
变得相对较大,您可能会遇到溢出。此外,我对二项式系数的实现不是最理想的

#define MIN(a,b) (((a)<(b))?(a):(b))

uint64_t gridTravel(uint64_t m, uint64_t n) {
    if (m == n && m == 1) {
        return 0;
    }

    uint64_t result = 1;
    for (uint64_t i = 1; i <= MIN(m - 1,n - 1); i++) {
        result *= (m + n - 1 - i);
        result /= i;
    }

    return result;
}
定义最小值(a,b)(a)