根据范围

时间:2018-01-30 01:02:17

标签: dynamic-programming

假设我有一个可以使用这两个标准保存数字的组:

  1. 它的范围为5,即最低和最高数字之间的差异可以达到5.
  2. 每组最多可容纳4个号码。
  3. e.g。如果我有数字1,2,3,4,6,8,10,11,13,16,17,18。如何在尽可能少的窗口中对这些数字进行分组?两个可能的答案:

    1. [1,2,3,4],[6,8,10,11],[13,16,17,18]
    2. [1,2,3],[4,6,8],[10,11,13],[16,17,18]
    3. 也许这不是最好的例子,但是有一个与此类似的编程问题吗?

1 个答案:

答案 0 :(得分:1)

这对于动态编程来说不是一个好问题。一个贪婪的算法就足够了。

这是一个非常粗略的草图,证明贪婪就足够了。

(remark-1)假设[x1, x2, ..., xN]是您输入的数字序列,[(1 = l1, r1), (l2, r2), ..., (lM, rM = N)]是1到N之间的索引对,用于描述(start, end)窗口,使所有这些窗口一起满足您的约束并覆盖序列中的所有数字。现在删除xN。显然,[x1, ..., xN]的旧封面可以转换为[(1 = l1, r1), ..., (lM, N - 1)]的新封面[x1, ..., x{N-1}],并且最多可以覆盖旧封面的窗口(或更少)。

(归纳)现在对N进行归纳,以显示贪婪的"尽可能多地从最后 - 列表" - 算法是最佳的。

  • 对于[x1],贪婪算法会找到封面[(1, 1)],这显然是最优的。

  • 假设贪婪算法找到所有K <{1}}的最佳覆盖率。 N.让[x1, ..., xK]成为MxN - xM <= maxWindowWidth的最小索引。让N - M <= maxElemsPerWindow成为涵盖Z所需的最佳窗口数。如果我们选择[x1, ..., x{M - 1}]作为任何(M', N)的最后一个窗口,那么通过(remark-1),M' > M的解决方案Z'将等于或低于[x1, ..., x{M'}] },即Z,我们总共需要Z' >= Z个窗口。由于贪心算法总是会删除尽可能多的元素,因此它会选择(Z' + 1) >= (Z + 1)作为最后一个窗口,最后总共有(M, N)个窗口,其中(Q + 1)是窗口数贪心算法将用于覆盖Q。但是通过归纳假设[x1, ..., x{M-1}],因此贪婪算法需要Q = Z窗口,这等于或优于任何其他解决方案Z + 1

因此,贪婪算法是最佳的。

这是Scala中的草图:

Z' + 1