我正在构建一个游戏,其中玩家被给予一组随机节点,并尝试通过按特定顺序放置节点来构建最长的列表。每个节点在侧面上具有零个或多个连接,这些连接必须与列表中下一个节点侧的至少一个连接匹配。例如,节点可能如下所示:
+--+
left connections A B right connections
B C
+--+
上述节点(示例节点)可以与任何这些节点连接:
+--+
C | This node can connect to the right side of the example node (matches C)
D |
+--+
+--+
B K This node can connect to the left side of the example node (matches A)
L A This node can connect to the right side of the example node (matches B)
+--+
所以,给定这三个节点,玩家可以在列表中匹配它们:
+--+ +--+ +--+
B K A B C |
L A -A- B C -C- D |
+--+ +--+ +--+
我需要验证玩家的选择。玩家不必首先以正确的顺序选择节点,但最终的选择必须能够连接到连续的线性列表。
因此,给定一系列无序节点(玩家选择),我需要将节点组成上面的有效列表,或者向玩家显示错误。
我可以强制验证,但我希望找到一个更优雅的解决方案。
答案 0 :(得分:1)
在哈希和一些预先计算之后,问题可能如下所示:
Given a graph determine whether it has a path traversing all nodes
正是the Hamiltonian problem。您可以阅读有关该主题的研究或分析图表的某些结构(对于某些特殊图表,它有简单的解决方案),但在一般情况下,我所知道的最佳解决方案是指数级的。
然而,直截了当的蛮力解决方案是通过所有排列(n!
)并检查它是否形成正确的路径(*n
)。这种方法导致O(n*n!)
渐近。实际上,这意味着n
最多应为12
以进行亚秒检查,而n=15
则需要几个小时才能检查最坏情况。
轻微优化 - 逐渐形成路径并检查每个新顶点 - 在最坏的情况下导致O(n!)
时间,因此可以在几秒钟内检查n=13
最坏的情况,甚至更快的平均值,因为很多假路径将在早期阶段被削减。
您可以更进一步,充分利用动态编程。让我们定义isProperPath[S][i]
(其中S
是节点子集的位掩码,i
是该子集的某个节点)作为对应于由对应于{的子集的节点构成的路径的存在的值{1}}与最后一个节点S
。然后,根据i
中包含较少元素的子集的所有值,可以轻松计算isProperPath[S][i]
:
S
按isProperPath[S][i] = false;
for (j in S) {
if (isProperPath[S\i][j] && hasConnection(j, i))
isProperPath[S][i] = true;
}
大小递增的顺序遍历所有S
和i
对,我们将计算所有值。当且仅当S
isProperPath[A][i] = true
是整个给定集合和A
- 任何节点时,答案才是真实的。
时间复杂度为i
,空间复杂度为O(2^n*n^2)
,因为有O(2^n*n)
个值,并且需要2^n*n
根据以前的值计算值。该算法可以使用大约O(n)
位或24
在亚秒内检查大小为400M
的大小集。