algorithm - 如何执行最小拆分以满足特殊的集合排序?

标签 algorithm set

我正在尝试创建一个算法来解决以下问题: Updated image of problem

输入是一个未排序的集合列表,其中包含整数对(键,值)。每对中的第一个在集合中是正数且是唯一的。
我想找到一种算法来拆分输入集,以便可以对集合进行排序,使得对于每个键,值在集合顺序中是不递减的。

有一个简单的解决方案是将集合拆分为每个单独的值并对它们进行排序,我想要在拆分的集合数量方面更有效的方法。

您是否遇到过任何类似的问题和/或可以建议的技术? 最优(最小分割数)解决方案听起来是否可能在多项式时间内实现?


编辑:在示例中,“<=”运算符表示对集合作为一个整体的约束,其中每个键值 (100、101、102) 的对应值等于或大于先前集合中的值 (或从集合中省略)。即使用输出集中的顺序提取每个键的值给出:

  • 键 100 {0, 1}
  • 键 101 {2, 3}
  • 键 102 {10, 15}

最佳答案

A*

我建议使用 A*以找到最佳解决方案。从左到右逐步构建拆分集的顺序,最大限度地减少实现此目标所需的集数。

A* 根据对总成本的一些启发式 估计访问状态。我建议 状态 由我们目前拥有的订单中已包含的所有对的总和来描述。如果每个键的所有值都不同,那么您可以通过简单地存储每个键的最后一个值来相当简洁地表示此信息。否则你将不得不以某种方式处理相等的值,这样你就知道哪些已经被包含,哪些没有。对于每个状态,您都会维护导致它的最佳顺序的某种表示,但是在状态保持不变的情况下,它可能会不断更新。

启发式 应该是对从开始到当前状态到目标的路径总成本的估计。它可以太低,但绝不能太高。在我们的例子中,启发式应该计算到目前为止订单中包含的(可能拆分的)集合的数量,并添加仍在等待插入的(未拆分的)集合的数量。由于剩余的集合可能需要拆分,这可能太低了,但由于您的集合永远不会少于仍在等待插入的集合,因此这是一种合适的启发式方法。

现在您有了一些状态优先级队列,按此启发式的值排序。您从中提取最少的项目,并且知道从队列中提取状态的那一刻,到达该状态的成本不能再减少,因此到达该状态的路径是最优的。现在你检查从中可以达到哪些其他状态:在 split 集的顺序中,哪些其他对可以是下一个?对于每个具有准备好包含的对的剩余集合,您创建一个新的后续状态,从集合中获取所有准备好的对。到目前为止,成本增加了一个。如果你设法拿走一整套,没有 split ,那么剩余成本的估计值会减少一个。

对于这个新状态,您检查它是否已经存在于您的优先级队列中。如果是,并且它之前的成本高于刚刚计算的成本,那么你更新它的成本,以及通向它的最优路径。确保优先键相应地更改其位置(“减少键”)。如果该状态之前不在队列中,则将其添加到队列中。

迪杰斯特拉

想想看,这与运行 Dijkstra's algorithm 是一样的以拆分次数作为成本。由于每条边的成本为零或成本为一,因此您可以更轻松地实现这一点,根本不需要任何优先级队列。相反,您可以使用两个集合,称为 S₀S₁,其中来自 S₀ 的所有元素都需要相同数量的拆分,而来自 S₁ 的所有元素都需要再拆分一次。用伪代码粗略勾画:

S₀ = ∅ (empty set)
S₁ = ∅
add initial state (no pairs added yet, all sets remain to be added) to S₀
while True
    while (S₀ ≠ ∅)
        x = take and remove any element from zero
        if x is the target state (all pairs included in the order) then
            return the path information associated with it
        for (r: those sets which remain to be added in state x)
            if we can take r as a whole then
                let y be the state obtained by taking r as the next set in the order
                if y is in S₁, remove it
                add y to S₀
            else if we can add only some elements from r then
                let y bet the state obtained by taking as many elements from r as possible
                if y is not in S₀, add it to S₁
    S₀ = S₁
    S₁ = ∅

关于algorithm - 如何执行最小拆分以满足特殊的集合排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11881685/

相关文章:

java - Android Parcelable - 使用通用数据类型将数据读/写到 Parcel

haskell - 为什么 IntSet 查找是 O(min(n,W)),而不是 O(1)?

algorithm - 这些循环可以执行多少次?

python - Leetcode Python 208. 实现Trie(前缀树)

algorithm - 实现模运算的更好方法(算法问题)

在其他多边形中找到最大的空矩形的算法

java - 如果我们只覆盖类中的 hashCode() 并在 Set 中使用它会发生什么?

c++ - 寻找输入的微小变化将导致哈希值发生微小变化的哈希算法

python - 在 Python 中计算 n 元重叠矩阵的最快方法

Python:测试动态变化的集合中的所有元素的最简单方法是什么?