改进的多米诺算法

时间:2016-12-12 08:02:07

标签: algorithm permutation matching

我试图解决多米诺骨牌的轻微变化,其中你给了一组多米诺骨牌,并且必须对它们进行排序以使不匹配的数量(当两个相邻的图块不具有相同的触摸编号,例如[1 | 3] [4 | 1] =不匹配)被最小化。此外,瓷砖不能旋转,只能变换(例如[1 | 3]不能旋转到[3 | 1]),

例如,假设您已获得图块:[1 | 2][4 | 2][2 | 3],您可以找到序列[1 | 2] [2 | 3] [4 | 2],其中只有1个不匹配最后2个瓷砖。

我为此制定了几种算法。通过计算所有排列,计算它们的分数并返回最佳排列,可以找到最佳(即最少数量的不匹配)。这也可以通过DP或回溯来改进,例如避免已经具有比当前最佳解决方案更差的得分的计算分支。这有效,但对于大型测试用例来说显然非常慢。我也找到了找到次优解决方案的方法,但在合理的时间内使用Tabu搜索和遗传算法等方法。

这些工作,但我正在寻找的是一个最佳解决方案,它将比我最初的蛮力解决方案所需的O(N!)更快地解决它。

然而,我怀疑这可能是不可能的。如果您将问题看作图形问题,我们会得到一个图形,其中图块是顶点和有向边(由于图块无法旋转而被定向)。然后它成为通过图找到最短哈密顿路径的问题,这是NP完全...

是否有另一种方法来构建它,以便在合理的时间内以最佳方式解决它?

1 个答案:

答案 0 :(得分:0)

我认为像O(2 ^ N * K)这样的东西是可行的,因为在链条中你并不真正关心里面的东西。

你可以使用DP超过2 ^ N * K阵列,其中N是瓦片数量(2 ^ N是包含瓦片的位掩码),K是最后一个触摸数字。

递归函数的原型将如下所示:

int solve(Bitmask mySet,int touchingNumber);

在这里,你在set(T)中遍历tile,检查它们的最后touchNumber是否等于touchingNumber。循环上次触摸数字(L)。现在找到所有L和T的最小值:

  • 给定T的候选者,L是求解(mySet-T,L),如果T.first == L

  • 给定T的候选人,L是解决(mySet-T,L)+1,如果T.first!= L

计算完毕后,求解参数的解决方案存储在全局数组中,并用于以后的调用。

对于给定的参数可能没有解决方案,您应该跳过这样的结果。

最终解决方案是所有可能的最后触摸数字和全套瓷砖的最小解决方案。