2

我有一个数组 a[i][j]。元素是 char,解释为集合 {1,...,8} 的子集(如果第 k 位为 1,则元素 k 在子集中)。我认为这无关紧要,但每个元素都设置了 4 位。

每一行 a[1][j]..a[n][j] 是 {1,...,8} 的子集的集合。我需要删除重复的行,如果可以通过 {1,...,8} 的排列从另一行获得两行,则将两行视为重复行。

示例(0bxxxxxxxx 表示二进制数):

0b11000000, 0b01100000, 0b00110000

是重复的

0b00110000, 0b00011000, 0b00100100

因为前者可以通过应用置换从后者获得

8->8, 7->7, 6->1, 5->4, 4->3, 3->2, 2->5, 1->6

并重新排序结果。

出于性能考虑,该数组包含大约 2000 行,每行最多包含 20 个元素。每一行都已经排序,如果这可能有帮助的话,这些行也是按字典顺序递增的。算法的其余部分是用 C 编写的,因此首选 C 解决方案。

谢谢你的帮助。

4

1 回答 1

0

如果所有子集都有 2 个元素,这将表示图同构,子集表示图边。这甚至更普遍(因此可能更难),所以我会看看用于解决图同构的启发式方法,看看它们是否适用于这里。

有很多图同构启发式可以廉价地排除同构。对于特定集合,您可以计算每个元素属于多少个子集,然后对其进行排序。在您的示例中,两个集合都会得到 [2,2,1,1,0,0,0,0]。如果两个集合的排序序列不同,则不存在同构。当然,平等并不能保证存在。

还有更多类似的启发式方法甚至可以更好地筛选出非同构图(并且可能适用于此)。

还有,8!只有 40320,所以暴力破解所有排列并非完全不可行。

于 2009-07-03T09:53:53.880 回答