【问题标题】:Variation of knapsack (or partition) algorithm背包(或分区)算法的变体
【发布时间】:2014-01-06 23:46:41
【问题描述】:

我遇到的问题如下:

给定一个包含 N 个项目的队列,每个项目都有一个权重,以及 K 个容器的队列。我们需要按照物品来的顺序将物品分配到容器中。例如,第一个项目只能进入第一个容器,第二个项目可以进入第一个或第二个但不能进入第三个(否则第二个容器将没有任何项目)。

我需要创建并实现一种算法来实现某种均匀分布,因此最重的容器必须尽可能轻巧;给出具有这种重量的容器的数量。

我想这是 3 分区或背包问题的一些变体。我已经使用动态编程实现了一种可能的分发解决方案,并尝试从其中使用的表中获取计数。但它不够有效(内存太贵),并且获取容器数量的算法不正确。

有人可以解释一下,哪种算法可以解决这个问题?

【问题讨论】:

  • N > K 时,最后的N-K 物品可以放在任何容器中吗?
  • 您的问题是否与Bin-Packing problem 或更普遍的Cutting Stock problem 没有更多共同点?
  • @Andy Jones,不,每个容器都应该使用,并且应该按顺序使用。所以我们可以将前 3 个项目放入第一个容器,然后将 5 个放入第二个容器,N-K 应该以某种方式在另一个容器之间分配。或者我只是没有清楚地理解你的问题。
  • @asQuirreL 谢谢,我会详细了解这个问题
  • 我可能遗漏了一些东西,但是您的问题可以改写为“”给定一个 n 元素数组,我们如何将它划分为 k 连续段,使得元素的最大总和任何部分都被最小化了?”因为如果是这样,您的问题是repeat of this one,它提供了一个高效的 DP 解决方案。或者您是否正在寻找比这更有效的东西?

标签: algorithm optimization dynamic-programming combinatorics


【解决方案1】:

所以OP的问题一般可以通过this question中给出的DP算法来解决。为了完整起见,我将在这里重复它的症结:

假设 d[i][j] 是当我们有项目 s[1], .., s[i] 时问题的解决方案 和 j 个容器。那么:

  1. d[0][j] = 0 对于每个 j
  2. d[i][1] = Sum(s[1], ..., s[i]) 每个
  3. d[i][j] = min(max(d[it][j-1], Sum(s[i-t+1], ..., s[i]) 1

但是,简单的实现会消耗 O(NK) 空间,这太多了。幸运的是,看(3):d[_][j]的值只取决于d[_][j-1]。这意味着一旦我们计算完所有d[_][j],我们就可以使用我们用来存储d[_][j-1] 的空间来存储我们即将计算的d[_][j+1] 的值。

由于d[0][j] 的值全为零,我们也不需要存储这些值。因此,我们需要存储的唯一数组是 O(N) 大小的 d[i][1]、保存 j-1th 迭代结果的 O(N) 大小的数组,以及 O(N) 大小的数组保存我们当前正在计算的jth 迭代的结果。总计:O(N)。

编辑:所以第一次,我实际上并没有回答 OP 关于如何计算最大重量的容器数量的问题。假设w[i][j] 持有i,jth 问题的最大重量,c[i][j] 是与最大重量匹配的容器数量。那么:

  1. c[0][j] = jw[0][j] = 0 对于每个 j
  2. c[i][1] = 1w[i][1] = Sum(s[1], .., s[i]) 对于每个 i
  3. u 等于上面 pt (3) 中选择的t
    • 如果d[i-u][j-1] > Sum(s[i-u+1], .., s[i])
      • 然后c[i][j] = c[i-u][j-1]w[i][j] = w[i-u][j-1]
      • 因为重量为Sum(s[i-u+1], .., s[i]jth 容器比重量为d[i-u][j-1] 的容器1, .., j-1 中最重的容器轻。
    • 如果d[i-u][j-1] < Sum(s[i-u+1], .., s[i])
      • 然后c[i][j] = 1w[i][j] = Sum(s[i-u+1], .., s[i])
      • 因为带有项目s[i-u+1], .., s[i]jth 容器是新的最重的容器。
    • 如果如果d[i-u][j-1] == Sum(s[i-u+1], .., s[i]):
      • 然后c[i][j] = c[i-u][j-1]+1w[i][j] = d[i-u][j-1]
      • 因为jth 容器与之前最重的容器重量相同。

同样,我们只需要使用恒定数量的 O(N) 大小的数组,整个时间为 O(N)

【讨论】:

  • 感谢您的回复。据我了解,该算法为我们提供了有关最大重量的信息。我如何获得有关具有这种重量的容器数量的信息?还是我错过了什么?
  • 完全忘记了,抱歉。编辑了一个解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
  • 1970-01-01
  • 2018-01-31
  • 2018-12-16
相关资源
最近更新 更多