C 单调路径区域的递归和

C 单调路径区域的递归和,c,recursion,path,area,C,Recursion,Path,Area,我试图找到一种递归的方法来找到从nxn网格的左上角到右下角(路径的每一步可以沿直线向右或向下)的所有单调路径的所有区域的总和 假设左下角有坐标(0,0),我有以下函数: int sum(int current_sum, int x, int y, int n){ if (x == n || y == 0) return current_sum; return (sum(current_sum+y, x+1, y, n) + sum(current_sum,

我试图找到一种递归的方法来找到从nxn网格的左上角到右下角(路径的每一步可以沿直线向右或向下)的所有单调路径的所有区域的总和

假设左下角有坐标(0,0),我有以下函数:

int sum(int current_sum, int x, int y, int n){
    if (x == n || y == 0)  
        return current_sum;

    return (sum(current_sum+y, x+1, y, n) + sum(current_sum, x, y-1, n));
}
,在到达网格右侧或底线时停止(从网格右侧移动不会改变区域的当前值),并考虑向右或向下移动所产生的区域总和。结果比应该的要大,我很难找出原因。有人能看一下吗


提前感谢再次阅读,OP的解决方案似乎已经正确了。下面是我的答案供参考。


这似乎是ProjectEuler,或者一个非常类似的问题

如果我理解正确,你想做的是:

  • 每一条路只走一次
  • 计算每个不同路径的数量,并将该路径下的面积添加到总和中
  • 以递归方式执行此操作将如下所示:

    int area(int x, int y)
    {
      if (x == 0 || y == 0)
        /* We are at the end of a path, terminate */
        return 0;
    
      /* We are not at the end, add the two choices possible from here */
      return area(x, y - 1) + area(x - 1, y) + y;
    }
    
    你必须画一个图来确认最后一个表达式是正确的。当我们在网格(-x)中向右移动时,我们只在总和上加y,这样就覆盖了我们下面的一列。向下移动(-y)不会覆盖任何区域

    此解决方案应该是正确的,但速度会非常慢。为了加快速度,您可以添加记忆,这意味着将区域(x,y)的中间结果保存到表中,并查找它,而不是每次都计算它。我不会为您编写解决方案,但这并不难做到。祝你好运

    […]从nxn栅格的左上角到右下角[…]

    您的代码不反映以下情况:

    // ...
      if (x == n || y == 0)  
        return current_sum;
    // ...
    
    想象一条完全水平的路径。例如,在2对3网格中,当索引以
    0
    开始,且左下角为
    (0 | 0)
    ,则右下角为
    (1 | 0)
    。现在考虑右上角,即<代码>(1×2)< /代码>。对于这些值,上述两个条件都不成立,因此您将对接下来两个单元格的递归调用求和:
    (2 | 2)
    (向右)和
    (1 | 1)
    (向下)

    第一个单元格(向右)就是问题所在:在那里,
    x==2==n
    ,因此返回路径的和,尽管它没有在右下角结束。因此,对太多路径求和,导致总体求和过大


    我认为这应该做到:

    unsigned sum_inner(
        unsigned const accumulatedSum,
        size_t const x, size_t const y,
        size_t const gridSideSize) {
      bool atRightEdge = (x == gridSideSize - 1);
      bool atBottomEdge = (y == 0);
      if (atRightEdge && atBottomEdge) {
        // Awesome, in lower right corner, so everything is fine
        // Except that with the implementation of the other two edge cases, this
        // will never be run (except for the 1x1 case)!
        printf("reached lower right edge!\n");
        return accumulatedSum + 1;
      } else if (atRightEdge) {
        // Right edge, so from here one can only go down. Since there's only one
        // possible path left, sum it directly:
        return accumulatedSum + y + 1;
      } else if (atBottomEdge) {
        // Bottom edge, so from here one can only go right. Since there's only one
        // possible path left, sum it directly:
        return accumulatedSum + (gridSideSize - x) + 1;
      } else {
        // Somewhere in the grid, recursion time!
        return sum_inner(accumulatedSum + y, x + 1, y, gridSideSize) +
               sum_inner(accumulatedSum, x, y - 1, gridSideSize);
      }
    }
    
    unsigned sum_monotonic_tl_br(size_t const gridSideSize) {
      return sum_inner(0, 0, gridSideSize - 1, gridSideSize);
    }
    

    我认为,添加一个包含输入、预期和实际输出的具体示例会有很大帮助。这是Euler项目的一个问题:关注回报。x+1,y-1。使用2步循环,x从低到高,y从高到低,怎么样?它可以绕过移动到零值墙。相关: