背包式算法

时间:2012-04-28 17:05:40

标签: java algorithm stack division

这是我发现的一个非常有趣的java问题:

在书籍印刷被发现之前,书籍被称为“作家”的某些人复制。 簿记员有一堆N本书需要复制。为此他有K作家。每本书都可以有不同数量的页面,每个作者只能从书架顶部拿书(如果他拿到书1,那么他可以拿书2而不是书4或书5)。簿记员知道每本书的页数,并且他需要在作者之间共享书籍,以便将作者必须复制的最大页数尽可能地最小化。当然,页面不能分开。你不能将30页的书分成15和15页。

例如,如果我们有7本书,其中有3位作家和相应的书籍页面:30 50 5 60 90 5 80那么最佳解决方案将是第一位作家拿下前4本书,第二位作者是下一本书和这是我们最后两本书的第三本:

1st = 145页
第2 = 90页
第3名= 85页

所以程序是编写一个算法,找到在编写器之间共享页面的最佳解决方案。因此,在程序结束时,您必须显示每个页面有多少页面。

这是多年前的编程竞赛,我想尝试一下,到目前为止我发现的是,如果你把所有书籍的总页数除以你的作者数量得到106.66页的示例,然后你尝试给每个作者提供最接近该数字的堆栈中的连续书籍,但是对于大页码而言根本不能很好地工作,特别是如果一本书有多少页面超过总页数除以作者数

所以,如果您愿意,可以分享您的意见并给出提示和提示,数学或其他什么,这是一个非常有趣的算法!

4 个答案:

答案 0 :(得分:1)

让我们假设你有书籍1 ... n,页面为b1,b2,...,bn。假设你有K作家。

初始化矩阵F [1 ... n,1 ... K] =无穷大。

设F [i,1] = sum_j = 1..i(bj)

现在,每个k = 2..K

F [i,k] = min_j = 1..i(max(F [j,k-1],sum_r = j + 1..i(br))

答案 1 :(得分:1)

我提出了一个直接的解决方案,也许不是很有效,但逻辑是有效的。基本上,你开始的作家数量与书籍数量相同,并且减少直到你拥有你的作家数量。

以示例显示。假设您从七个值开始,30 50 5 60 90 5 80.对于每个步骤,通过总计“最低对”将其减少一个。以粗体显示的值是进行下一次迭代的对。

7
30 50 5 60 90 5 80
6
30 55 60 90 5 80
5
30 55 60 90 85
4
85 60 90 85
3
145 90 85

通过一些伪编程,这个例子说明了如何实现它

main(books: { 30 50 5 60 90 5 80 }, K: 3)

define main(books, K)
  writers = books
  while writers.length > K do
    reduceMinimalPair(writers)
  endwhile
end

define reduceMinimalPair(items)
  index = 0
  minvalue = items[0] + items[1]
  for i in 1..items.length-1 do
    if items[i] + items[i + 1] < minvalue then
      index = i
      minvalue = items[i] + items[i + 1]
    endif
  endfor
  items.removeat(index)
  items.removeat(index + 1)
  items.insertat(index, minvalue)
end

答案 2 :(得分:0)

我认为你认为的方式是正确的,但是如果你说它对大数字不起作用那么你应该检查是否存在比平均值更大的数字并在那种情况下做其他事情。也许删除这个数字并从一开始就把它给作家或其他东西

答案 3 :(得分:0)

使用动态编程替代解决它,您还可以二进制搜索每个人不会复制超过此页数的页面上限。当这个数字收敛时,就是答案。

相关问题