C 给出错误结果的动态规划递归

C 给出错误结果的动态规划递归,c,algorithm,dynamic-programming,C,Algorithm,Dynamic Programming,我试图解决背包问题的一个变体,并为它编写了一个递归解决方案。但我的解决方案是返回一个错误的值。我想我的算法有缺陷。你能帮我找到故障吗 这是我的密码 int calc_budget(int b, int i){ // If we have reached the end if(i >= nParty){ tbl[b][i] = 0; return tbl[b][i]; } //If remaining capa

我试图解决背包问题的一个变体,并为它编写了一个递归解决方案。但我的解决方案是返回一个错误的值。我想我的算法有缺陷。你能帮我找到故障吗

这是我的密码

int calc_budget(int b, int i){
    // If we have reached the end
    if(i >= nParty){
            tbl[b][i] = 0;
            return tbl[b][i];
    }

    //If remaining capacity is not able to hold the ith capacity, move on to next element
    if(budget[i] > b){
            if(tbl[b][i+1] == 0){
                    tbl[b][i+1] = calc_budget(b,i+1);
            }
            return tbl[b][i+1];
    }
    else{   //If the ith capacity can be accomodated
            //Do not include this item
            if(tbl[b][i+1] == 0){
                    tbl[b][i] = calc_budget(b,i+1);
            }

            // Include this item and consider the next item
            if(tbl[b-budget[i]][i+1] == 0){
                    tbl[b-budget[i]][i] = fun[i] + calc_budget(b-budget[i], i+1);
            }

            // We have the results for includinng ith item as well as excluding ith item. Return the best ( max here )
            return max(tbl[b][i], tbl[b-budget[i]][i]);
    }

}
问题的目标:通过优化使用给定的最大预算,找到最大乐趣

以下是我的意见

budget[3] = {19,12,19}
fun[3] = {2,4,5}
calc_budget(30,0)
allowed budget: 30
该程序的正确答案应为5。我的回来了。我在尝试调试时绘制了递归树。我的发现:在选择项目0(右子树)时,val=2+(11,1)。这(11,1)将导致最大值((11,2)和0)。(11,2)为5,因此最终结果为2+5=7。在这种DP技术中,我的算法不应该选择11,2,因为预算的总和超过了给定值。但这是我为递归DP找到的基本框架。这是算法有缺陷还是我弄错了

谢谢


奇丹巴拉姆

问题在于,在调用
计算预算(b,i)
期间,您为
[b][i]
以外的其他索引编写了
tbl
字段。我将尝试使用
计算预算(b,I)
的递归定义来解释这个问题

我们首先定义递归关系。让
F(b,i)
成为你与当事人
i,…,n
和最大预算
b
的最大乐趣。那么

F(b, n+1) = 0
F(b, i)   = F(b, i+1) // if budget[i] > b
          = max( F(b, i+1), fun[i] + F(b - budget[i], i+1) ) // otherwise
到目前为止还不错。
calc_budget(b,i)
应该准确地计算这个数字,并且应该使用
tbl
作为已经计算值的缓存。换句话说,在第一次调用
计算预算(b,i)
后,
tbl[b][i]==F(b,i)
必须为真

下面是一些实现这一点的伪代码:

initialize tbl[b][i] = -1 for all b, i.

def calc_budget(b, i):
    if tbl[b][i] != -1: return tbl[b][i]

    if i == n + 1:
        tbl[b][n+1] = 0
    else:
        if budget[i] > b:
            tbl[b][i] = calc_budget(b, i+1)
        else:
            tbl[b][i] = max( 
                            calc_budget(b, i+1), 
                            fun[i] + calc_budget(b - budget[i], i+1)
                           )

    return tbl[b][i]

我希望您现在同意,由于
tbl
实际上只是已计算值的缓存,因此在调用
calc\u budget(b,I)
时编写例如
tbl[b-budget[I][I]
似乎很奇怪

首先,我认为0不足以表明以前是否计算过子问题,因为有些子问题的答案实际上是0。 其次,代码中有一个错误,您应该在返回值之前设置tbl[b][i]的值。 试试这个:

// We have the results for includinng ith item as well as excluding ith item. Return the best ( max here )    
tbl[b][i]=max(tbl[b][i], tbl[b-budget[i]][i]);
return tbl[b][i];
希望有帮助