【问题标题】:Is this a non-polynomial problem? If not, how can it be solved in polynomial time?这是一个非多项式问题吗?如果不是,如何在多项式时间内解决?
【发布时间】:2021-03-30 13:15:29
【问题描述】:

问题:

编写一个有 2 个输入参数的函数:

  • items:2 元组正整数的列表/向量(即 >= 1)
  • target:正整数(即 >= 1)

找到一个元组子集,这样:

  • 子集的第一个元组元素之和大于或等于输入target
  • 子集的第二个元组元素的总和是minimal,我们称这个总和值为best

该函数应该只返回best。此外,保证有解决方案。换句话说,所有第一个元组元素的总和总是大于或等于目标。

这是这样一个函数的伪代码签名:

(items: List<(int, int)>, target: int) -> int

这里有一些例子……

示例 A:

  • 项目 = [(25,50), (49,51), (25,50), (1,100)]
  • 目标 = 50
  • 回答 = 100

示例 B:

  • 项目 = [(25,50), (49,51), (25,50), (1,5)]
  • 目标 = 50
  • 回答 = 56

这是我简单的指数时间解决方案:

  1. 遍历所有可能的子集(因此是指数时间)
  2. 对于每个子集,计算第一个元组元素的总和
  3. 如果该总和大于或等于目标,则计算第二个元组元素的总和
  4. 如果新的总和是迄今为止找到的最小的,则更新最小值

我还尝试确定问题的数学属性是否允许使用快捷方式,例如按最大的“第一个元素除以第二个元素”比率检查项目(最划算)。但是,正如示例 A 所示,这并非对所有情况都有效。

这是一个非多项式问题吗?如果不是,如何在多项式时间内求解?

【问题讨论】:

  • @FélixPoulin-Bélanger 网站的不同部分对此有不同的感受。关注[算法]的人不介意,但关注[python]和[性能]的人可能想要更多实际问题。这个问题有点难——就像knapsack problem 一样,只是你要决定从背包中取出哪些物品,以便遵守重量限制,并且你试图最大化背包中剩余的价值。

标签: algorithm big-o


【解决方案1】:

这是一个0-1背包问题:https://en.wikipedia.org/wiki/Knapsack_problem

元组是项目,第一个元组元素是项目值,第二个元组元素是项目权重。经典的背包询问“best 是否小于某个特定限制。

因此,这个问题是 NP 完全的,没有多项式时间解。

有正常的动态规划解决方案可以适应在 O(items.length * best) 中工作。最简单的方法是使用普通的 DP 方法,首先对 best 设置一个较小的限制,然后将其加倍,直到可以达到目标值。

【讨论】:

  • 嗯,没有已知多项式时间解。
  • 感谢您提及背包问题!据我了解,它使背包中物品的价值总和最大化,以使重量总和小于或等于容量。我的问题是相反的:最小化背包中物品的重量总和,使值的总和大于或等于目标。然而,这种对称性可能意味着这两个问题是等价的。
  • @MattTimmermans:我不确定这是一个 0-1 背包问题。 items 输入是一个列表,而不是一个集合。因此,每个“项目”可以具有不同的最大副本数。例如,在示例 A 中,项目 (25,50) 可以有两个副本,但其他两个项目只能有一个副本。但是感谢您向我指出背包问题,阅读更多关于它的内容肯定会对我有所帮助!
猜你喜欢
  • 1970-01-01
  • 2015-07-06
  • 2021-06-10
  • 1970-01-01
  • 2011-04-12
  • 2012-09-20
  • 1970-01-01
  • 2013-11-07
  • 2018-09-12
相关资源
最近更新 更多