如何将给定递归程序转换为动态规划(DP)实现形式?
递归加法转动态规划的解决方案
看起来你在把递归加法函数改成动态规划(DP)形式时卡壳了,没关系,我们一步步来拆解这个问题。首先我先补全你没写完的递归add函数(推测是最常见的加法递归实现),然后再讲解如何转成自底向上的DP版本。
首先,先还原完整的递归代码(假设你的递归逻辑是这样的):
int add(int, int); int main() { int x = 0, y = 0; printf("Enter positive integers x, y: "); scanf("%d %d", &x, &y); printf("Result: %d\n", add(x, y)); return 0; } int add(int x, int y) { // 处理非法输入 if(x < 0 || y < 0) { printf("Input must be positive!\n"); return -1; } // 基例:其中一个数为0时,直接返回另一个数 if(x == 0) return y; if(y == 0) return x; // 递归步骤:x减1,y加1,直到触发基例 return add(x - 1, y + 1); }
动态规划改写思路
既然你已经了解DP的自底向上思想,那我们从状态定义、初始状态、状态转移三个核心点入手:
状态定义:我们可以用
dp[i][j]表示计算add(i,j)的结果。不过因为加法的特殊性,其实可以不用数组,直接用迭代模拟,但为了清晰展示DP思路,先从二维DP表说起。初始状态(对应递归基例):
- 当
i=0时,dp[0][j] = j(任何数加0等于它本身) - 当
j=0时,dp[i][0] = i(同理)
- 当
状态转移方程:对应递归的步骤,
add(i,j) = add(i-1, y+1),但自底向上时,我们可以转化为更直接的递推关系:dp[i][j] = dp[i-1][j] + 1(因为add(i,j)比add(i-1,j)大1)。
改写后的DP代码
方式一:无数组的迭代版(高效简洁)
因为加法的递归逻辑本质是逐步将一个数减到0,所以我们可以直接用循环模拟这个过程,这是最简洁的自底向上实现:
int add_dp(int x, int y) { if(x < 0 || y < 0) { printf("Input must be positive!\n"); return -1; } // 自底向上迭代:模拟递归的"减x加y"过程 while(x > 0) { x--; y++; } return y; }
方式二:二维DP表版(清晰展示DP思想)
如果想完整体现DP的状态填充过程,可以用二维数组来实现:
int add_dp(int x, int y) { if(x < 0 || y < 0) { printf("Input must be positive!\n"); return -1; } // 创建DP表,大小为(x+1)*(y+1),覆盖所有可能的输入状态 int dp[x+1][y+1]; // 初始化基例状态 for(int j = 0; j <= y; j++) { dp[0][j] = j; } for(int i = 0; i <= x; i++) { dp[i][0] = i; } // 自底向上填充DP表,从最小的i,j开始计算到目标x,y for(int i = 1; i <= x; i++) { for(int j = 1; j <= y; j++) { dp[i][j] = dp[i-1][j] + 1; } } return dp[x][y]; }
额外说明
其实用DP来实现加法确实有点“大材小用”,因为它的本质就是简单的算术运算,但这个例子非常适合理解DP自底向上的核心思想:从已知的基础状态出发,逐步推导到目标状态。如果你的递归add函数有其他特殊逻辑(比如不是简单加法),可以把完整的递归代码补充出来,我再帮你调整DP实现。
内容的提问来源于stack exchange,提问作者MasterGL
相关产品推荐
相关产品推荐

