具有两个权重的背包算法

Max*_*lop 5 algorithm knapsack-problem dynamic-programming greedy time-complexity

我有以下问题:

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

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

谁能给我提示。谢谢。

uSe*_*sed 3

您可以将元素分为两部分,一部分具有w1重量,另一部分具有w2重量。

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

A1 :按成本降序排序,权重为w1的元素

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

现在您可以创建两个数组的前缀和,让我们调用它们P1, P2

例子 :

Array : 11, 8, 5, 3, 1

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

获得前缀和后,您可以迭代数组P1并尝试包含直到第 i 个索引的元素。一旦我们包含了 upto 的元素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
}
Run Code Online (Sandbox Code Playgroud)

总体复杂度为O(n * log n).

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

  • 这看起来像是唯一考虑价值/成本的解决方案(公平地说,OP 可能更清楚问题包括这些)。您可以将内部循环中的二分搜索替换为从 P2 末尾向后行走的指针 j,但这不会提高时间复杂度,因为排序仍然占主导地位。 (2认同)