【问题标题】:knapsack algorithm with two weights具有两个权重的背包算法
【发布时间】:2016-11-05 03:59:22
【问题描述】:

我有以下问题:

解决背包0-1问题(不是分数)假设每个 对象的权重为w1w2(只有两个权重)。容量=W,算法 必须在 O(nlogn) 上运行。

我试过解决,贪心算法不行,动态规划算法是O(n*W)。

谁能给我提示。 谢谢。

【问题讨论】:

    标签: algorithm time-complexity dynamic-programming knapsack-problem greedy


    【解决方案1】:

    您可以将元素分成两部分,一份以w1 作为权重,另一份以w2 作为权重。

    现在您可以根据成本对以上两个列表进行排序。

    A1:按cost降序排列,权重为w1的元素

    A2 : 按成本降序排序,权重为 w2 的元素

    现在您可以创建两个数组的前缀总和,我们将它们称为P1, P2

    示例:

    Array : 11, 8, 5, 3, 1

    Prefix sum : 11, 19, 24, 27, 28

    获得前缀总和后,您可以遍历P1 数组并尝试将元素包含到第i 个索引。 一旦我们包含直到i 的元素,我们就剩下W - (w1*i) 权重,然后我们可以尝试在P2 数组中对这个权重进行二分搜索。

    伪代码:

    A : input array
    create A1 : cost of elements having w1 weight
    create A2 : cost of elements having w2 weight
    
    sort(A1, descending)
    sort(A2, descending)
    
    for(i=0;i <= A1.size();i++){
          P1[i] = P1[i-1] + A1[i];
          P2[i] = P2[i-1] + A2[i];
    }
    int ans = 0;
    for(i=1;i<=A1.size();i++){
          if(i * w1 <= W){
                int wLeft = W - i * w1;
                int ans = binarySearch(wLeft, P2) + p1[i];  
          }
    }
    ans => contains the answer
    
    //-----------Binary search function
    int binarySearch(int weight, P2[]){
          int start = 0, end = P2.size(), ans = 0;
          int mid = (start+end)/2;
          while(start <= end){
                if(mid * w2 <= weight){
                      start = mid + 1;
                      ans = max(ans, p2[mid]);
                }else{
                      end = mid - 1;
                }
          }
    return ans
    }
    

    整体复杂度为O(n * log n)

    正如@j_random_hacker 所建议的,我们可以迭代第二个前缀数组,因为我们只能通过添加元素来改进解决方案,它会通过删除二进制搜索来简化代码。

    【讨论】:

    • 这看起来是唯一考虑价值/成本的解决方案(公平地说,OP 本可以更清楚地表明问题包括这些)。您可以将内部循环中的二分查找替换为从 P2 末尾向后走的指针 j,但这不会提高时间复杂度,因为排序仍然占主导地位。
    • 我认为这个算法有一些拼写错误:P1[i] = P[i-1] + A1[i]; - 不应该是P1[i] = P1[i-1] + A1[i];吗? (下一行也是如此)。另外,我不确定ans 机制是否准确。最后,binarySearch 是否有可能在else 分支中缺少某些内容?但是,也许我错了:-)
    • @Zvika 感谢您指出错误已修复。为什么你认为 ans 机制不准确,你能提供一些它可能失败的示例案例吗?我不认为在 else 的情况下有什么遗漏,如果你能指出一些具体的错误就好了。
    【解决方案2】:

    由于您可以使用两种权重:

    首先使用尽可能多的元素 w1 或可以放入 W 中。在它们之后尽可能多的 w2。

    当你得到这样的背包时,在每次迭代中从中弹出一个 w1 元素,并放入尽可能多的 w2 或你有的。只要背包中有 w1 元素,就可以这样做。

    所有迭代中背包的最大重量将是你的答案,算法将在 O(n) 中运行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-04
      • 2016-05-28
      • 1970-01-01
      • 2017-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多