为啥在 0-1 背包问题中我们使用 INT_MIN 以及为啥 0 不起作用

Posted

技术标签:

【中文标题】为啥在 0-1 背包问题中我们使用 INT_MIN 以及为啥 0 不起作用【英文标题】:why in 0-1 Knapsack problem we use INT_MIN and why the 0 is not working为什么在 0-1 背包问题中我们使用 INT_MIN 以及为什么 0 不起作用 【发布时间】:2021-09-03 07:47:48 【问题描述】:

为什么在 0-1 背包问题中 INT_min 用于 (max

#include<iostream>
using namespace std;
int solve(int v[],  int w[] , int n ,int max)
    if (max < 0) 
        return INT_MIN;      // here this is giving me problem if I use 0 in place of 
                            // INT_min I get wrong ansewrs
    
 
    if (n < 0 || max == 0) 
        return 0;
    
    
    int include = 0 ; 
    int exclude = 0 ;
    include = v[n]+solve(v,w, n-1,max - w[n]); 
    exclude = solve(v,w, n-1,max); 
    
    if(include<exclude)
        return exclude;
    else
        return include;
    

int main()
    int v[] =  20, 5, 10, 40, 15, 25 ;
    int w[] =  1, 2, 3, 8, 7, 4 ;
    int W = 10;
 
    int n = sizeof(v) / sizeof(v[0]);

    cout<< solve(v,w,n-1,W)<<endl;
    return 0;

对于这个数组,如果我在返回语句中使用 INT_MIN,我得到答案 60,如果我在返回语句中使用 0,我得到 65。

【问题讨论】:

请注意,在这种情况下,编写一个返回 0 而不是 INT_MIN 的背包实现是可能的(实际上更好)。 INT_MIN 的使用在这里有点技巧。 【参考方案1】:

假设我们正在手动模拟递归过程。

首先,我们选择最后一个对象 (v=25, w=4) 并删除最后一个对象 (15v, 7w)。现在我们有 25 个值和 4 个权重。之后,在下一步N-3 中,N 是对象的数量,我们将确定是否包含最后三分之一的对象(40v, 8w)。

那么这里是当前步骤中的两个后续递归调用:

include = 40+solve(v,w, N-4,(10 - 4) - 8);
exclude = solve(v,w, N-4,(10-4)); 

如果在max &lt; 0 时返回INT_MIN,则include = 40 + INT_MIN = SOME_EXTREMELY_SMALL_VALUE。和exclude = SOME_NON_ZERO_VALUE &gt; include。考虑到当前剩余容量仅为10-4=6,这意味着不能拾取最后三分之一的对象,因为它会溢出背包。

如果改为返回0,则返回include = 40+0=40。和exclude = SOME_VALUE &lt; 40。这意味着实际上除了最后一个对象外,最后一个第三个对象也被拾取,即使它刚刚超出背包,导致总重量为4+8=12&gt;10 和无效答案40+25=65

【讨论】:

你的回答太复杂了,能不能用简单的形式给出 正如@Stef 所说,INT_MIN 只是将max &gt; 0 的情况标记为无效的技巧。如果不将这些标记为无效,则将背包装满将被视为可能的解决方案,这会给出错误的答案。 你觉得哪个部分比较复杂? @Dummy 如果我返回 0,过度填充如何成为有效情况,这无关紧要,应该退出值为 0 的函数实例。 0 在递归中返回给它的父 solve(v, w, N-3, 4) 函数。在solve(v, w, N-3, 4) 内部,solve(v,w, N-4,(10 - 4) - 8) 的计算结果为0,所以include = 40 + 0 = 40include 将与小于includeexclude 进行比较。所以这个include被选中,最终答案是include + PREVIOUSLY_CHOSEN_OBJECTS = 40 + 25 = 65

以上是关于为啥在 0-1 背包问题中我们使用 INT_MIN 以及为啥 0 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

用回溯法做0-1背包问题,这两行(程序中标注)是干嘛?为啥又要减?

2袋0-1背包的算法?

2个相同容量的背包-为啥我们不能两次找到最大值

编程求解:为啥依赖背包进行01背包之后,就可以用分组背包来解决了?

为啥会产生浮点异常?

图解算法-怎么用动态规划解决0-1背包问题