【问题标题】:Count number of paths in a grid using dynamic programming?使用动态编程计算网格中的路径数?
【发布时间】:2015-02-19 17:22:13
【问题描述】:

一个机器人坐在 NxN 网格的左上角。机器人只能向两个方向移动:向右和向下,其中一些单元格已死,即机器人无法进入该单元格。机器人有多少条可能的路径?
这可以使用回溯解决,但它的时间复杂度太高。我已经使用回溯解决了这个问题,但在最坏的情况下需要 O(2^n)。

bool exist(bool a[][], int i, int j,int N){
        return i>=0 && j >=0 && i < N && j < N;
    }
    int search(bool  a[][], int i, int j,int N){
        if(!exist(a,i,j,N) || a[i][j] == 1)
            return 0; // no path here.
        if(i == N-1 && j == N - 1){
            return 1; // 1 path here.
        }
        a[i][j] = 1; // mark that we have seen this spot here
        int paths = 0; // introduce a counter...
        paths += search(a, i,j+1,N); // add the additional paths as we find them
        paths += search(a, i+1,j,N);
        a[i][j] = 0;
        return paths; // return the number of paths available from this point.
    }

这里的单元格为 1 表示死单元格。有什么方法可以通过使用 DFS 或动态规划等来降低时间复杂度?

【问题讨论】:

  • 还有什么问题?
  • 降低时间复杂度...
  • 这不是一个问题...

标签: c++ algorithm dynamic-programming depth-first-search backtracking


【解决方案1】:

这可以通过认识到到特定节点的路径数只是到左侧节点的路径数 + 到上面节点的路径数的总和来解决。您只需要提出一种算法来以正确的顺序处理节点,即仅在处理其“父节点”之后才处理节点。我相信这可能是 O(n)。

【讨论】:

  • n 是网格的一侧时,我认为您的意思是 n ^2.
  • 是的,对于 n x n 网格 O(n^2),如果 n 表示节点数,则 O(n)。
【解决方案2】:

给定一个NxN grid,让ways[i][j] = number of possible paths from grid[0][0] to grid[i][j]

初始化grid[0][0] = 1

如果grid[i][j] is deadways[i][j] = 0

else ways[i][j] = ways[i-1][j] + ways[i][j-1](但要小心边缘)

一个例子:

grid:(1 means dead)   ways:

0 0 1 0 0             1 1 0 0 0
0 0 0 0 0             1 2 2 2 2
0 1 0 0 1             1 0 2 4 0
1 0 0 0 0             0 0 2 6 6
0 0 0 0 0             0 0 2 8 14

我认为复杂性是O(n^2),因为有n*n 网格。

【讨论】:

  • 你能给我一个链接吗?有没有可能grid[0][0]已经死了?
【解决方案3】:

让我们假设以下 3x3 网格,其中网格中的 1 表示障碍物

[0, 0, 0]
[0, 1, 0]
[0, 0, 0]

在这种情况下,唯一路径的数量是 2。 我们可以使用动态编程方法来降低时间复杂度,找到唯一路径,这是 C++ 中的代码

int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
       int m = obstacleGrid.size();
       int n = obstacleGrid[0].size();

    vector<vector<int> > arr(m,vector<int>(n,0));

    if (obstacleGrid[0][0]==1){return 0;}
    arr[0][0]=1;
    for (int i=1;i<m;i++){
        if (obstacleGrid[i][0]!=1){
            arr[i][0] = arr[i-1][0];
        }
    }
    for (int i=1;i<n;i++){
        if (obstacleGrid[0][i]!=1){
            arr[0][i] = arr[0][i-1];
        }
    }
    for (int i=1;i<m;i++){
        for(int j=1;j<n;j++){
            if (obstacleGrid[i][j]!=1){
                arr[i][j] = arr[i][j-1] + arr[i-1][j];
            }
        }
    }   
    return arr[m-1][n-1];
}

这种情况下的时间复杂度是 O(mn)。

【讨论】:

  • 您是否有理由建议从这么多问题中删除标签 [queue]?
  • 我正在过滤掉问题中包含不必要标记队列的问题,以便人们根据队列标签搜索问题不会很困难
  • @Bector 我在 python 中实现了您的代码,但无法使其工作。我认为原因之一可能是您正在设置 arr[0][0]=1; 而该值可能是 2(在您的示例中,它是)。
猜你喜欢
  • 1970-01-01
  • 2016-07-31
  • 2017-11-06
  • 1970-01-01
  • 2016-02-14
  • 2016-03-30
  • 2022-06-15
  • 1970-01-01
  • 2021-08-05
相关资源
最近更新 更多