在不计算其他人的情况下获取前缀

时间:2013-01-05 18:49:52

标签: algorithm math permutation

我读到这个post,这与我遇到的问题非常接近,但无法概括。 我正在尝试通过使用多个CPU搜索所有路径来解决旅行销售人员。 我需要的是一种将路径前缀编码为整数并将其分配给每个CPU的方法,以便它知道它应该扫描哪些路径。 例如,如果城市的数量是10,一个可能的3前缀(假设前缀长度是固定的并且已知)是4-10-3(有10 * 9 * 8前缀),那么接收它的CPU将会搜索以4-10-3开头的所有路径。 由于城市数量相当大,我无法计算n!因此我不能使用上面的帖子。

2 个答案:

答案 0 :(得分:2)

排列的标准表示形式使用Lehmer codes中表示的factorial number system。这个想法是n个元素的每个排列可以映射到n个数的序列,第一个在0到(n - 1)的范围内,第二个在0到(n - 2)的范围内。然后,这个数字序列可以表示为阶乘数系统中的单个整数。

我认为应该有可能使这个技巧适用于排列的前缀而不是整个排列。假设您有n个元素并且想要选择它们的k的排列。为此,首先计算部分置换的Lehmer代码。您将获得一系列k数字,而不是获得n个数字的序列。例如,给定从c a d得出的部分排列a b c d e f g,您的Lehmer代码将如下所示:

  • ca b c d e f g
  • 的第二个(零索引)元素
  • aa b d e f g
  • 的第0个零索引元素
  • db d e f g
  • 的第一个(零索引)元素

所以Lehmer代码是(2, 0, 1)

获得此Lehmer代码后,您可以尝试将其编码为单个整数。为此,您可以使用修改的阶乘数系统编码。具体来说,您可以尝试执行以下操作。如果你有n个元素并想要对它们进行k的置换,那么对于最后一个元素,总共会有(n - k + 1)个可能的选择。对于倒数第二个元素,总共有(n - k + 2)种可能的选择,(n - k + 3)可能选择倒数第三个元素,等等。因此,你可以选择你的Lehmer代码并执行以下操作:

  1. 保持最后的数字不变。
  2. 将倒数第二个元素乘以(n - k + 1)。
  3. 将倒数第三个元素乘以(n - k + 1)(n - k + 2) 4 ...
  4. 将第一个元素乘以(n - k + 1)(n - k + 2)......(n - 1)
  5. 总结这些价值观。
  6. 这会为置换产生唯一的整数代码。

    例如,我们的Lehmer代码为(2, 0, 1),n = 7,k = 3.因此,我们计算

      

    1 + 0×(7 - 3 + 1)+ 2×(7 - 3 + 2)(7 - 3 + 3)

         

    = 1 + 2×(5×6)

         

    = 5 + 2×30

         

    = 61

    要反转此过程,您可以获取整数并通过此过程向后运行以恢复部分Lehmer代码。要做到这一点,首先取数字并除以(n - k + 1)(n - k + 2)...(n - 1)以取回Lehmer代码的第一个数字。然后,将数字修改为(n - k + 1)(n - k + 2)...(n - 1)以丢弃第一个数字。然后,将数字除以(n - k + 1)(n - k + 2)...(n - 2)以返回Lehmer代码的第二个数字,然后通过(n - k + 1)mod( n - k + 2)...(n - 2)下降第二个数字。重复此操作,直到重建了Lehmer代码的所有数字。

    例如,给定前缀61,n = 7和k = 3,我们将从61除以7×6 = 30开始。这给出2,余数为1.因此,Lehmer代码的第一个数字是2 。修改30,我们得到数字1.接下来,我们除以6.这给出0,余数1.因此第二个数字是0.最后,我们读取剩余的数字,这给出了Lehmer的最后一位数字。代码,1。我们已经恢复了我们的Lehmer代码(2, 0, 1),我们可以从中轻松地重建排列。

    希望这有帮助!

答案 1 :(得分:1)

这里最简单的方法是映射前缀而不将其作为排列的一部分进行处理。不要将前缀映射到[0,10 * 9 * 8-1],而是映射到[0,10 * 10 * 10-1],因此前缀0,4,5将映射到数字45,并且前缀4,1,9将被映射到数字419(假设总共有10个城市,当然)。