找到要携带的最大权重子集

时间:2015-02-11 12:11:08

标签: algorithm

一个人的物品重量不足。

[10,10,12,15,16,20,45,65,120,140,​​150,178,198,200,210,233,298,306,307,310,375,400,420, 411,501,550,662,690,720,731,780,790]

他可带回家的最大重量是3公斤(3000克)。他想要尽可能多地保持警惕。

注意我尝试了回溯算法,但是它给了我等于我正在寻找的总和的子集,但是在我找不到相等的匹配总和然后它失败的情况下。我想找到接近总和的子集。

2 个答案:

答案 0 :(得分:1)

这是subset sum problem中可以解决的Dynamic Programming - 通过遵循以下递归公式,它基本上是回溯的有效实现:

D(0,n) = True
D(x,0) = False  | x > 0
D(x,n) = D(x-arr[i], n-1)           OR      D(x,n-1)
               ^                                ^
       item i is in subset         item i is not in subset

通过使用自下而上的动态编程(创建矩阵并从低到高填充它)或自上而下的动态编程(记住每个结果并检查它是否已在递归之前计算),这可以在{{1}中解决},其中O(n*W)是元素的数量,n是子集的大小(在您的情况下为3000)。

如果您运行自下而上的DP,则W的最大值x是您可以携带的最大权重。为了找到实际的项目,应该跟随表格,检查在每个决策点添加的项目,并生成添加的项目。返回实际集合在线程中解释了更多细节:How to find which elements are in the bag, using Knapsack Algorithm [and not only the bag's value]?(此线程正在处理背包问题,这是您问题的变体,每个项目的权重=成本)

答案 1 :(得分:0)

使用Backtracking,我们可以像这样构建解决方案,
我们将尝试使用此伪代码返回最接近但也低于给定重量的子集的最大权重:

func(weight_till_now,curr_pos)
    if(weight_till_now > max_possible) return 0
    if(curr_pos >= N) return 0

    // Taking this weight in current subset
    weight =  max(weight_till_now,func(weight_till_now+wt[curr_pos],curr_pos+1))

    // Not taking in current subset
    weight =  max(weight_till_now,func(weight_till_now,curr_pos+1))

    return weight

调用此函数时,初始参数为0,0将给出答案,因为这将使每个子集也尝试获得所有可能子集权重的最大权重,如果它变得大于最大可能权重那么这将返回0。