【问题标题】:Why my code didn't work correct in this problem为什么我的代码在这个问题中不能正常工作
【发布时间】:2021-03-21 08:48:13
【问题描述】:

网格旅行问题

她基本上是递归问题,就是这样:grid travel problem

这是我的解决方案:

#include <stdio.h>
#include <string.h>

int gridtravel(int r, int c) {
    if (r == 1 && c == 1) return 1;
    if (r == 0 || c == 0) return 0;
    return gridtravel(r - 1, c) + gridtravel(r, c - 1); 
}

int main() {
    int r, c;
    scanf("%i%i", &r, &c);
    printf("%i\n", gridtravel(r, c));
}

但是当我想用这样的解决方案降低时间复杂度时,我得到了一个不正确的结果:

#include <stdio.h>
#include <string.h>

int gridtravel(int r, int c, int arr[][c]) {
    if (arr[r][c] != 0) return arr[r][c];
    if (arr[c][r] != 0) return arr[c][r];
    if (r == 1 && c == 1) return 1;
    if (r == 0 || c == 0) return 0;
    arr[r][c] = gridtravel(r - 1, c, arr) + gridtravel(r, c - 1, arr);
    return arr[r][c];
}

int main() {
    int r, c;
    scanf("%i%i", &r, &c);
    int arr[r][c];
    for (int i = 0; i <= r; ++i) {
        for (int j = 0; j <= c; ++j) {
            arr[i][j] = 0;
        }
    }
    printf("%i\n", gridtravel(r, c, arr));
}

【问题讨论】:

  • 是时候将其放入调试器并找出原因了。
  • 定义数组时给出的“大小”是元素的数量,而不是顶部索引。所以r 元素数组的索引从0r - 1,包括在内。这一切都意味着您超出了数组的范围,这会导致 未定义的行为
  • 请注意,您在每次递归调用时传递的 VLA 类型更改int arr[][c]int arr[][c - 1] 不同),但应该相同。跨度>
  • arr[c][r] 不能正确

标签: c recursion dynamic-programming


【解决方案1】:

这里有一些问题:

  • 您的代码具有未定义的行为,因为初始化循环写入超出数组末尾:for (int i = 0; i &lt;= r; ++i) 应该是 for (int i = 0; i &lt; r; ++i)for (int j = 0; j &lt;= c; ++j) 应该是 for (int j = 0; j &lt; c; ++j)。您也可以将其简化为memset(arr, 0, sizeof(arr))

  • 此外,您必须将数组维度与单元格坐标分开传递。

  • 数组必须分配为方阵,因为您同时访问arr[r][c]arr[c][r]

  • 考虑到你使用缓存数组的方式,它应该多分配一行和一列。

  • 如果x 大于0,您应该利用gridtravel(1,x)gridtravel(x,1) 都是1 这一事实。

这是修改后的版本:

#include <stdio.h>
#include <string.h>

int gridtravel(int r, int c, int n, int arr[][n]) {
    if (arr[r][c] != 0) return arr[r][c];
    if (arr[c][r] != 0) return arr[c][r];
    if (r == 0 || c == 0) return 0;
    if (r == 1 || c == 1) return 1;
    return arr[r][c] = gridtravel(r - 1, c, n, arr) + gridtravel(r, c - 1, n, arr);
}

int main() {
    int r, c;
    if (scanf("%i%i", &r, &c) != 2 || r < 1 || c < 1)
        return 1;
    int n = (r > c) ? r + 1 : c + 1;
    int arr[n][n];
    memset(arr, 0, sizeof arr);
    printf("%i\n", gridtravel(r, c, n, arr));
    return 0;
}

【讨论】:

    【解决方案2】:

    主要问题:

    • 的边界是 c-1r-1
    • 您不能交换索引cr
    • 二维数组并不那么容易处理。

    如果你想使用大数组 malloc 可以比使用堆栈更好。

    对于二维数组,您必须将大小作为参数提供

    这里的代码用 printf 修改以跟随旅行

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int gridtravel(int n, int r,int c, int (*arr)[n]){
        printf("travel to %d %d\n", r, c);
        if(arr[r][c]!=0) return arr[r][c];
        if(r==1 && c==1) return 1;
        if(r==0 || c==0) return 0;
        
        arr[r][c] = gridtravel(n, r-1, c, arr)+gridtravel(n, r, c-1, arr);
        return arr[r][c];
    }
    
    int main(){
        int r,c;
        scanf("%i%i",&r,&c);
        int (*arr)[c] = malloc(sizeof(int[r][c]));
        memset(arr, 0, r*c*sizeof(int));
        printf("%i\n",gridtravel(c, r - 1, c - 1, arr));
        free(arr);
    }
    

    【讨论】:

      猜你喜欢
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多