1

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

这是我的代码。

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]);
    }

}

Objective of the problem: To find the maximum fun by optimally using the given max budget

以下是我的输入。

budget[3] = {19,12,19}
fun[3] = {2,4,5}
calc_budget(30,0)
allowed budget: 30

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

谢谢

奇丹巴拉姆

4

2 回答 2

0

首先,我认为 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];

希望能帮助到你!

于 2013-04-12T09:46:01.360 回答
0

问题是,在通话期间,您为其他索引calc_budget(b, i)编写字段而不是. 我将尝试使用递归定义来解释这个问题。tbl[b][i]calc_budget(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用作已经计算值的缓存。换句话说,在第一次调用之后calc_budget(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它实际上只是一个已经计算过的值的缓存,所以tbl[b-budget[i]][i]在调用calc_budget(b, i).

于 2013-04-10T15:53:05.577 回答