问题描述
我正在尝试将动态编程应用于以下问题:
“一个机器人位于mxn网格的左上角。该机器人只能在任何时间点向下或向右移动。该机器人正试图到达网格的右下角。有唯一的路径吗?”
int uniquePaths(int m,int n)
{
if (m==1 || n==1)
{
return 1;
}
else
{
return (uniquePaths(m,n-1)+uniquePaths(m-1,n));
}
}
我可以看到,如果我们能够保存uniquePath调用的输出,这将很有用,因为许多操作将多次执行。我对如何实现此目标的一个想法是创建一个m x n数组,然后将输出存储在那里。但是,这意味着我需要将数组输入到我的递归函数中,并且我认为对于这个问题,我只允许输入两个整数。有一种简单的方法可以应用此方法吗?
解决方法
您不需要将数组作为函数参数输入。它可以是局部变量。
天真的方式:使用递归函数
如果您真的想使用递归函数,可以在uniquePaths
中声明数组,然后调用另一个将使用该数组并进行计算的函数。
int uniquePaths_helper(int *grid,int m,int n,int i,int j);
int uniquePaths(int m,int n)
{
int *grid = malloc(m * n * sizeof(int));
int k;
for (k = 0; k < m * n; ++k)
{
grid[k] = 0;
}
return uniquePaths_helper(grid,m,n);
}
int uniquePaths_helper(int *grid,int j)
{
if (grid[i * m + j] == 0)
{
if (i == n - 1 || j == n - 1)
{
grid[i * m + j] = 1;
}
else
{
grid[i * m + j] = (
uniquePaths_helper(grid,n,i+1,j)
+ uniquePaths_helper(grid,i,j+1)
);
}
}
return grid[i * m + j];
}
变得更聪明:以正确的顺序填充数组
在先前的解决方案中,存在很多开销,因为我们必须使用默认值初始化数组,然后在每个递归调用中,我们都需要检查值是否已经存储在数组中或是否需要计算。 / p>
您可以简化所有操作。使用您的公式在grid
的单元格上直接填充数组,而不是在递归调用的参数上填充数组。
公式为:grid[i * m + j] == grid[(i+1) * m + j] + grid[i * m + j+1]
。
唯一棘手的部分是找出填充数组的顺序,以便可以将该公式写为简单的赋值,用==
替换=
。
由于单元格中的值仅取决于具有更高的i
和j
索引的值,因此我们可以简单地向后填充数组:
int uniquePaths(int m,int n)
{
int *grid = malloc(m * n * sizeof(int));
int i,j;
for (int i = 0; i < n; ++i)
grid[i * m + m-1] = 1;
for (int j = 0; j < m; ++j)
grid[(n-1) * m + j] = 1;
for (i = n - 2; i >= 0; --i)
{
for (j = m - 2; j >= 0; --j)
{
grid[i * m + j] = grid[(i+1) * m + j] + grid[i * m + j+1];
}
}
return grid[0];
}