你怎么能用动态编程转换下面的递归?

时间:2018-04-02 16:41:59

标签: c algorithm recursion dynamic-programming

如何使用动态编程(DP)转换以下递归程序? 我尝试将此代码重新定义为动态编程形式时遇到了一些麻烦。我得到了基本案例并确定了一般情况,我知道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){
        fprintf(stderr, "Negative Integer received!\n");
        return -1;
    }
    if (x == 1 || y == 1)
        return 1;
    else
        return add(x, y-1) + add(x - 1, y) + add(x-1, y-1);
}

2 个答案:

答案 0 :(得分:1)

您的代码将导致所有可能的x,y和z整数(负,正)组合的堆栈溢出

答案 1 :(得分:1)

为什么要以递归方式执行此操作?有一种迭代的方式,迭代'几乎总是'胜过递归。除此之外,代码更少:

int DP[500][500];
memset(DP, 0, sizeof(DP));
for(int i=1; i<=x; i++) DP[i][1] = 1;
for(int i=1; i<=y; i++) DP[1][i] = 1;

for(int i=2; i<=x; i++) {
    for(int j=2; j<=y; j++) {
        DP[i][j] = DP[i-1][j-1] + DP[i-1][j] + DP[i][j-1];
    }
}

printf("Result: %d\n", DP[x][y]);

但是如果你坚持递归,你可以通过指针传递你的DP数组。并且每次检查你之前是否计算过DP [i] [j],如果是这样的话不再计算并返回:

#include <stdio.h>
#include <string.h>

void add(int x, int y, int (*M)[500])
{
    if(M[x][y] > 0) return;

    if (x == 1 || y == 1) {
        M[x][y] = 1;
        return;
    }

    add(x, y-1, M);
    add(x - 1, y, M);
    add(x-1, y-1, M);

    M[x][y] = M[x][y-1] + M[x-1][y] + M[x-1][y-1];
    return;
}

int main()
{
    int x, y;
    printf("Enter x, y: ");
    scanf("%d %d", &x, &y);

    int DP[500][500];
    memset(DP, 0, sizeof(DP));
    add(x, y, DP);

    printf("Result: %d\n", DP[x][y]);

    return 0;
}