【问题标题】:Identify this Algorithm: Slots and Pegs识别此算法:插槽和钉子
【发布时间】:2009-02-06 12:42:23
【问题描述】:

我有许多插槽和钉子排成一条直线。钉子可以移动,并且需要分别移动到一个插槽中。只有当所有的钉子都被拿走时,一个插槽才能空着。当一个钉子被移动时,它不能越过另一个钉子。换句话说,必须保持挂钩的顺序。优选地,所有钉移动的总距离应保持在最小值。应尽可能将钉子放在最近的可用插槽中。

我只想知道:哪个数学领域处理这样的问题?处理类似问题的任何知名算法的名称是什么?我正在寻找谷歌饲料。一些关键字。

+--oooo-+--+---+---o--+------+--+-ooo+o-+-------o--+-----o-o-+-o

+ - Slots
o - Pegs


编辑:我认为这种可视化更有意义。它们是两个独立的轨道,需要排队。

Slots: +-------+--+---+------+------+--+----+--+----------+---------+--
Pegs:  ---oooo------------o--------------ooo-o---------o--------o-o---o

编辑:只是想明确一点,槽的数量可以大于、小于或等于钉子的数量。

【问题讨论】:

  • "钉子可以移动,需要分别移动到一个插槽中。"
  • @tehvan,这个想法是填补空缺;任何额外的钉子都不动。
  • 我不明白这里某些答案中使用的符号。我不懂函数式编程。我会在研究完该主题后立即选择一个接受的答案。感谢您的所有贡献。 BRB。

标签: algorithm math


【解决方案1】:

我认为这是dynamic programming 解决方案的经典素材。事实上,看一下“序列对齐”,这可能是该维基百科页面上另一个很好的搜索词。

关键的见解是这样的:

假设您将挂钩作为挂钩位置列表(挂钩 1:更多挂钩),将插槽作为插槽位置列表(插槽 1:更多插槽)。调用这个问题(peg1:pegs, slot1:slots)。那么解决方案是 slot1 中的 peg1 和 (pegs, slots) 的解决方案,或者是 (peg1:pegs, slots) 的解决方案。

这给出了如何解决它的递归定义。

或者用伪代码(以函数式编程风格编写),想象一个函数距离(peg, slot):

distance([]) = 0
distance((peg,slot):matches) = distance(peg,slot)+distance(matches)

solution(peg:[], slot:[]) = [(peg,slot)]
solution(peg:pegs, slot:slots) = if distance(a)<distance(b) then a else b
   where a = solution(peg:pegs, slots) and b=(peg,slot):solution(pegs, slots)

应该通过将距离组合到数据结构中来提高此解决方案的效率。

【讨论】:

  • 我认为这行不通:考虑“o--xo”或((1,5),(4))。然后你的算法要我们比较槽 1 中的 peg 1 和 ((5,()) 和 ((1,5),())。这两个子问题是平凡无解的,填一个槽总比没有槽好. 所以解决方案是将 1 挂在插槽 1 中,成本为 3(续)
  • ... 但是很容易看出更好的解决方案是在插槽 1 中以 1 为代价将 2 钉住。话虽如此,这对于 DP 来说似乎是个问题。
  • 公平点,此解决方案仅在每个挂钩至少有一个插槽时才有效。但是提问者暗示“可以移动钉子并且需要将每个钉子移动到一个插槽中”。如果您还想留下钉子,只需在交换钉子和插槽的情况下再次运行,速度会降低 2 倍
【解决方案2】:

我不知道这个问题来自哪里,但我很确定它是combinatorial optimization 的一种形式,更具体地说,可以使用(integer) linear programming 解决。

【讨论】:

  • 我认为这是错误的,但如果您能提供更多详细信息,我很乐意被说服。整数线性规划通常是 NP 完备的,而这个问题肯定不是
【解决方案3】:

"所有钉子移动的总距离 应保持在最低限度”

除非我遗漏了什么,否则这不是问题。

由于必须保持钉子的顺序,您只需将钉子编号为 1、2、3、...

+--1234-+--+---+---5--+------+--+-678+9-+-------10--+ -----11-12-+-13

最终状态必须是插槽 1 中的 peg 1,插槽 2 中的 peg 2,等等。

+--1-+-2-+-3-+-4-+-5-+-6-+-7-+-8-+-9-+-10-+-11-+- 12-+-13-+

不能将钉子相互跳过无关紧要,每个钉子都必须从起点到终点移动一定的距离。 只要所有的移动方向都正确,并且钉子永远不需要后退,那么每个钉子必须移动的距离就是一个简单的常数(它不会t 取决于移动的顺序),以及这些距离的总和,您的成本函数也是恒定的。

我认为这里不需要动态规划或线性规划优化问题。

如果您引入一个挂钩并放下它的成本,那么这里可能存在优化问题,但即使这样也可能是微不足道的。

编辑以回应 1800 Information 的评论

只有当数量 插槽等于挂钩的数量 - 这不是问题中的假设 声明 – 1800 条信息(2 小时 以前)

好的,我错过了。感谢您指出我所缺少的。不过,我仍然不相信这是火箭科学。

假设有 # 个钉子 > # 个孔。像上面那样计算最终状态,就好像你有额外的洞一样;然后选择移动最远的 N 个钉子并将它们从问题中删除:那些是没有移动的钉子。忽略这些挂钩重新计算。

假设 # 个孔 > # 个钉子。正确的最终状态可能有也可能没有差距。如上计算最终状态并寻找相邻钉子相互移动的位置。这些是您可以将其分解为可以轻松解决的子问题的点。当连续子问题的两端都有洞时,还有一个额外的变量——最终的连续序列开始的地方。

是的,它比我一开始想象的要复杂一些,但它似乎仍然需要一些纸笔工作来表明解决方案是几个易于理解和编码的循环。

【讨论】:

  • 只有当插槽数等于挂钩数时才成立 - 问题陈述中没有假设这一点
【解决方案4】:

组合学。组合算法。具体数学。 (还有标题 an excellent and relevant book Donald Knuth。

【讨论】:

    【解决方案5】:

    如果挂钩数 == 槽数,则仅存在一种解决方案。 第一个挂钩必须进入第一个插槽,下一个挂钩必须进入下一个插槽,依此类推。

    数字不同,然后稍微复杂一些,因为一个钉子或插槽(我们可以移动哪个无关紧要)可以移动到很多地方。

    蛮力: 假设对象的数量是 m 钉和 n 槽(可互换),m

    1. 对于每路 (n-m) 个插槽可以 选择(参考一些组合学 算法看看如何做到这一点)
      1. 有 (n-m) 个选定的插槽将是空的。
      2. 用钉子填充剩余的 m 个插槽。计算移动的距离。这与顶部讨论的情况相同。
    2. 选择移动距离最小的排列方式。

    递归解决方案:

        int solve(int pegs, int *peg_x, int slots, int *slot_x)
        {
          if (slots > pegs )
            return solve(slots, slot_x, pegs, peg_x);
          if (slots == 0 || pegs==0)
            return 0; // Cannot move
    
          int option1 = INT_MAX, options2 = INT_MAX;
    
    
          if (pegs > slots ) // Can try skipping a peg
            option1 = solve(pegs-1, peg_x+1 /* Move over one element */
                              slots, slot_x);
          // pegs >= slots 
          option2 = solve(pegs-1, peg_x+1, slots-1, slot_x+1)
                    + abs(peg_x[0]-slot_x[0]);
          return min(option1, option2);
        }
    

    这个解决方案仍然需要将结果存储在一个表中,这样子问题就不会被多次解决,成为一个动态解决方案。

    思考....会更新.....

    【讨论】:

    • Sid 有一些不错的见解,但您的算法需要组合时间才能完成。您正在详尽地评估 m! /n! / (m-n)!可能的解决方案。这实际上可能需要数年才能完成。
    【解决方案6】:

    排队理论或数学...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-19
      • 2020-02-25
      • 2013-05-13
      • 2020-04-18
      • 1970-01-01
      • 2011-06-22
      相关资源
      最近更新 更多