分数背包的最佳案例

时间:2016-11-15 05:18:07

标签: algorithm time-complexity knapsack-problem

分数背包的最坏情况运行时间是O(n),那么它应该是最好的情况呢?是O(1),因为如果一个重量限制是16并且你得到第一个有价值的项目,是不是?

2 个答案:

答案 0 :(得分:1)

  

如果您假设输入是按值排序的顺序给出的话,则为True !!!

但是根据定义,算法也需要采用非排序输入。 see this.

如果您正在考虑可能排序或未排序的正常输入。然后有两种方法可以解决这个问题:

  1. 对输入进行排序。即使在最好的情况下,如果你使用气泡/插入排序也不能小于O(n)。这看起来完全是愚蠢的,因为这两种排序算法都具有O(n ^ 2)avarage /最差情况下的性能。
  2. 使用weighted medians方法。这将花费你O(n),因为找到加权中位数将采用O(n)。这种方法的代码如下。
  3. 分数背包的加权中位数法

    我们将在以下代码中处理每单位项目的价值。代码将首先找到中间值(即,如果以排序顺序给出,则每单位项目的值的中间值)并将其置于其正确位置。我们将使用快速排序分区方法。一旦我们得到中间(称之为mid)元素,需要考虑以下两种情况:

    1. mid右侧的所有项目的权重总和超过W的值时,我们需要在mid的右侧搜索我们的答案。< / LI>
    2. 否定中间右侧的所有值(称为v_left)并在中间左侧搜索W-v_left(包括mid)。
    3. 以下是python中的实现(在任何地方只使用浮点数):

      请注意,我没有向您提供生产级别代码,并且有些情况也会失败。想想在阵列中找到第k个最大值会导致最坏情况/失败的原因(当所有的值都相同时)。

      def partition(weights,values,start,end):
          x = values[end]/weights[end]
          i = start
          for j in range(start,end):
              if values[j]/weights[j] < x:
                  values[i],values[j] = values[j],values[i]
                  weights[i], weights[j] = weights[j],weights[i]
                  i+=1 
      
      
          values[i],values[end] = values[end],values[i]
          weights[i], weights[end] = weights[end],weights[i]
      
          return i
      
      
      def _find_kth(weights,values,start,end,k):
          ind = partition(weights,values,start,end)
          if ind - start == k-1:
              return ind
          if ind - start > k-1:
              return _find_kth(weights,values,start,ind-1,k)
          return _find_kth(weights,values,ind+1,end,k-ind-1)
      
      def find_kth(weights,values,k):
          return _find_kth(weights,values,0,len(weights)-1,k)
      
      
      def fractional_knapsack(weights,values,w):
          if w == 0 or len(weights)==0:
              return 0
      
          if len(weights) == 1 and weights[0] > w:
              return w*(values[0]/weights[0])
      
          mid = find_kth(weights,values,len(weights)/2)
      
          w1 = reduce(lambda x,y: x+y,weights[mid+1:])
          v1 = reduce(lambda x,y: x+y, values[mid+1:])
      
          if(w1>w):
              return fractional_knapsack(weights[mid+1:],values[mid+1:],w)
      
      
          return v1 + fractional_knapsack(weights[:mid+1],values[:mid+1],w-w1)
      

答案 1 :(得分:0)

(与@ Shasha99讨论后编辑和重写答案,因为我觉得2016-12-06之前的答案有点欺骗)

<强>摘要

如果项目已经排序,

O(1)最好的情况是可能的。否则最好的情况是O(n)

<强>讨论

如果物品没有排序,你需要找到最好的物品(对于一个物品已经填满背包的情况),而单独的物品需要O(n),因为你必须检查所有物品。因此,最好的情况是O(n)

在另一端,你可以有一个所有物品都适合的背包。不需要搜索最佳,但您需要全部放入其中,因此它仍然是O(n)

更多分析

有趣的是,O(n)最坏的情况并不意味着物品被分类。 显然来自http://algo2.iti.kit.edu/sanders/courses/algdat03/sol12.pdf的想法与快速中位数选择算法(加权中位数或中位数中位数?)配对。感谢@ Shasha99找到这个算法。

请注意,普通的快速选择预期为O(n)O(n*n)最差,但如果您使用的中位数中位数最差为O(n)。缺点是相当复杂的算法。

我对任何算法的工作实现感兴趣。更多来源(希望简单)算法也不会受到伤害。