当前位置: 首页 > 知识库问答 >
问题:

将动态规划集成到递归解中

仇正豪
2023-03-14

我正在尝试将动态编程应用于以下问题:

“机器人位于m x n网格的左上角。机器人只能在任何时间点向下或向右移动。机器人正试图到达网格的右下角。有多少独特的路径?”

我有一个递归的解决方案,我认为效果很好。然而,它是缓慢的:

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数组并将输出存储在其中。但是,这意味着我需要将数组输入到我的递归函数中,我认为对于这个问题,我只允许输入两个整数。有没有简单的方法来应用它?

共有1个答案

呼延光明
2023-03-14

不需要将数组作为函数参数输入。它可以是一个局部变量。

如果真的想使用递归函数,可以在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, 0, 0, m, n);
}

int uniquePaths_helper(int *grid, int m, int n, int i, 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,m,n, i+1, j)
                + uniquePaths_helper(grid,m,n, i, j+1)
            );
        }
    }
    return grid[i * m + j];
}

在之前的解决方案中,由于我们必须使用默认值初始化数组,因此会产生大量开销,然后在每次递归调用时,我们都需要检查值是否已存储在数组中或需要计算。

你可以走捷径。在网格的单元格中直接使用公式填充数组,而不是递归调用的参数。

公式是:grid[i*m j]==grid[(i 1)*m j]grid[i*m j 1]

唯一棘手的部分是找出填充数组的顺序,这样这个公式就可以写成一个简单的赋值,用=替换=

由于单元格中的值仅取决于具有更高ij索引的值,我们可以简单地向后填充数组:

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];
}
 类似资料:
  • 本文向大家介绍动态规划和带记忆递归的区别相关面试题,主要包含被问及动态规划和带记忆递归的区别时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 自顶而下和自底而上

  • 我有一个子集问题的工作代码,如果它发现一个子集等于所需的目标,它可以打印数字。 > 我想打印给定目标的所有可能的子集,我不知道要为此更改什么。 我如何让它对负数起作用?

  • 斐波那契数列 1. 爬楼梯 2. 强盗抢劫 3. 强盗在环形街区抢劫 4. 信件错排 5. 母牛生产 矩阵路径 1. 矩阵的最小路径和 2. 矩阵的总路径数 数组区间 1. 数组区间和 2. 数组中等差递增子区间的个数 分割整数 1. 分割整数的最大乘积 2. 按平方数来分割整数 3. 分割整数构成字母字符串 最长递增子序列 1. 最长递增子序列 2. 一组整数对能够构成的最长链 3. 最长摆动子

  • 给定一个数组,是否可以从起始索引开始选择一组整数,这样该组就与给定的目标相加?但是,附加的限制是必须选择所有的6。 groupSum6(0,[5,6,2],8)true groupSum6(0,[5,6,2],9)false groupSum6(0,[5,6,2],7)false 只是想弄清楚我错在哪里。声明nums[start]==6的特殊情况是不是错误的方法?

  • 我正在为动态编程编写一些复习材料。我需要提出如何划分子问题,计算出基本情况,并提出递归公式。 给定 n 个正整数 a1,a2,...,an、一个数字 k 和一个目标 W,我们希望选择一个子集 T,其总和恰好是 k 个元素,其总和最接近 W。每个元素只能选择一次。定义一个具有 3 个参数的子问题(即 C[x,y,z] = ...)。 我只处理过几个动态编程示例,从未处理过定义子问题时需要3个参数的示

  • 本文向大家介绍请你说一下递归和动态规划的区别?相关面试题,主要包含被问及请你说一下递归和动态规划的区别?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 递归法是算法调用自身,动态规划是将一个问题分解成若干个子问题,对大问题的求解转化为对子问题的求解。动态规划有时可以通过递归实现,通常用在最优问题的求解