【问题标题】:Dynamic Programming recursion giving out wrong result动态规划递归给出错误的结果
【发布时间】:2013-04-10 11:57:03
【问题描述】:

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

这是我的代码。

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 找到的基本框架。这个算法有缺陷还是我弄错了。

谢谢

奇丹巴拉姆

【问题讨论】:

    标签: c algorithm dynamic-programming


    【解决方案1】:

    问题在于,在调用calc_budget(b, i) 期间,您为[b][i] 之外的其他索引编写了tbl 字段。我将尝试使用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)

    【讨论】:

      【解决方案2】:

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

      希望对你有帮助!

      【讨论】:

        猜你喜欢
        • 2014-05-22
        • 1970-01-01
        • 1970-01-01
        • 2014-06-26
        • 2013-11-14
        • 2012-07-10
        • 2011-11-09
        • 2020-11-20
        • 2013-10-09
        相关资源
        最近更新 更多