使用n个标签标记网格,其中每个标签与每个其他标签相邻

时间:2013-08-08 12:52:45

标签: algorithm matrix grid adjacency-matrix

我正在尝试使用n个单独的标签创建一个网格,其中每个单元格都标有n个标签中的一个,这样所有标签都与网格中某处的所有其他标签相邻(边缘)(我不在乎哪里)。标签可以根据需要自由出现多次,我希望网格尽可能小。例如,这是一个五个标签的网格,1到5:

3 2 4
5 1 3
2 4 5

虽然手工生成这个对于少量标签来说并不是太糟糕,但是对于较大的数字而言,生成合理大小的网格似乎非常困难,因此我希望编写一个程序来生成它们,而不需要采取蛮力搜索。我想这之前一定要进行调查,但我发现的最接近的是De Bruijn tori,这并不是我想要的。任何帮助将不胜感激。

编辑:感谢Benawii提供以下改进说明:

  

“给定一个整数n,生成最小的可能矩阵,其中对于每对(x,y),其中x≠y且x,y∈{1,...,n}存在一对相邻的单元格值为x和y的矩阵。“

1 个答案:

答案 0 :(得分:0)

您可以尝试使用简单的贪婪算法。

我认为我不能给你一个严格的数学证明,至少因为问题没有严格定义,但算法非常直观。

首先,如果您有1 ... K个数字(K个标签),那么您需要至少K *(K-1)/ 2个相邻单元格(连接)才能完全覆盖。大小为NxM的矩阵生成(N-1)* M +(M-1)* N = 2 * N * M-(N + M)个连接。

由于您没有在“最小矩阵”下提及您的理解,我们假设您的意思是该区域。在这种情况下,很明显,对于给定区域,方阵将产生更大数量的连接,因为它具有与其他4个相邻的更多“内部”单元。例如,对于区域16,矩阵4x4优于2x8。 “更好”是直观的 - 更多的联系和更多的机会达到目标。因此,让我们使用目标方矩阵并根据需要展开它们。上式将变为2 * N *(N-1)。

然后我们可以尝试以下贪婪算法:

  1. 对于输入数K,找到N,使得2 * N *(N-1)> K *(K-1)/ 2。一个简单的学校方程式。
  2. 保留邻接矩阵M,为所有i设置M [i] [i] = 1,为其余对设置0。
  3. 初始化大小为NxN的结果矩阵R,填充“空值”标记,例如使用-1。
  4. 从左上角开始并向右下方迭代:

    for (int i = 0; i < N; ++i)
            for (int j = 0; j < N; ++j)
                    R[i][j];
    
  5. 对于每个这样的R [i] [j](现在是-1)找到这样一个“最适合”的值。同样,“最合适”是一个直观的定义,在这里我们理解这样一个值将有助于新的未使用的连接。因此,创建一组已经填充的单元格邻居数 - S,其大小最多为2(上邻居和左邻居)。然后找到第一个k,这样对于S中的两个数字x,M [x] [k] = 0。如果没有这样的数字则尝试至少一个新连接,如果没有数字,即使是一个,则两个邻居都被完全覆盖,放一些数字从这里揭开 - 可能是'最坏情况'中的那个 - 这样的x,其中Sum(M [x] [i])是最小的。在任何情况下,当有几个可供选择时,你也应该选择“最糟糕的情况”。
  6. 设置R [i] [j]的值后,不要忘记用S - M [R [i] [j]] [x] = M [x] [R]中的数字x标记新连接[i] [j]] = 1。
  7. 如果矩阵已填满且M中仍有未标记的连接,则将另一行追加到矩阵并继续。如果在结束之前找到所有连接,则删除多余的行。
  8. 您可以查看此算法,看看会发生什么。第5步是玩耍的地方,特别是猜测在相同的情况下选择哪一个(几个数字可以同样'最糟糕的情况')。

    示例:

    对于K = 6,我们需要15个连接:

    N = 4,我们需要4x4方阵。该理论认为4x3矩阵有17个连接,所以它可能适合,但我们将尝试4x4。

    以下是上述算法的输出:

    1234
    5615
    2413
    36**
    

    我不确定你能用4x3做,也许是......:)