我目前正在调查一个路由问题(找到一个地方子集[每个都有一定分数]我想访问但不超过最长旅行时间)并提出了1/0背包的变化似乎解决了我原来问题的问题。
据维基百科称,1/0背包被描述为:
给定一组具有质量和值的项目,确定要包含在集合中的每个项目的数量,以使总权重小于或等于给定限制,并且总值与可能的。
因此,对于每个项目,都有一个固定的重量(质量),可以在尝试解决问题时轻松使用,例如使用动态编程。
但是,如果特定商品的重量取决于包的先前内容,该怎么办?换句话说(以更一般的方式):让我们考虑以下完整的图表:
每个节点(A,B,C,D,E)代表我可能想要放入背包的物品。假设每个节点也分配了一个值(在图中省略)。我仍然希望有一个最佳的背包,因此是具有最高分数的节点的子集,但是这次重量(或将特定节点添加到我当前的背包的成本)不分配给节点本身而是分配给边缘导致它。
这意味着添加节点的成本取决于背包的先前内容(例如,通过使用来自任何已包含节点的成本最低的边缘)。例如,如果我当前的背包由{A,C}组成,则添加B的成本为2(采用A-> B或C-> B)。如果我目前的背包由{D,E}组成,则添加B的成本为3。
不幸的是,我无法提出一个很好的算法来解决这个问题。 经典的背包DP方法在这里并不真正起作用,因为您可以轻松地构建不返回最优解的情况。例如,如果你开始使用"错误的"节点添加一个非常好的节点(应该包含在一个最佳的解决方案但很晚才尝试)的成本可能超过容量。
我对这个问题采取了完全错误的方法吗?你认为有更好的算法来解决这个问题吗?
答案 0 :(得分:2)
首先,这个问题是NP难的。这是从加权完整图中的最短哈密顿路径到这一路径的缩减。给定一个图形,我们可以将所有节点的值分配给1,然后在答案上运行二进制搜索。如果存在针对此问题的多项式解,则可以判断是否存在包含所有顶点并且不长于给定值的路径。因此,我们将能够在多项式时间内解决最短的哈密顿路径问题。在实践中,这意味着没有人知道对您的问题有效的正确多项式解决方案。
现在有两种方法:
如果顶点数量相当小(大约20),则可以使用动态编程来获得精确解。州是(mask, last_vertex)
。该值是我们访问mask
中所有顶点并停在last_vertex
中所需的最短时间。此解决方案的时间复杂度为O(2^n * n^2)
。
如果顶点数量更大,您可以找到近似解。有很多方法可以做到:启发式,不同的贪心算法,随机抽样和局部优化等等。