您可以尝试一个简单的贪心算法。
我不认为我能给你一个严格的数学证明,至少因为这个问题没有严格定义,但算法是相当直观的。
首先,如果您有 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)。
然后我们可以尝试下面的贪心算法:
- 对于输入数 K,找到 N 使得 2*N*(N-1)>K*(K-1)/2。一个简单的学校方程。
- 保持邻接矩阵 M,对所有 i 设置 M[i][i]=1,对其余的对设置 0。
- 初始化大小为 NxN 的结果矩阵 R,填充“空值”标记,例如 -1。
从左上角开始并从右向下迭代:
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
R[i][j];
- 对于每个这样的 R[i][j](现在是 -1),找到一个“最适合”的值。同样,“最适合”是一个直观的定义,在这里我们理解这样一个值,它将有助于一个新的未使用的连接。出于这个原因,创建一组已填充的单元格邻居数 - S,其大小最多为 2(上邻居和左邻居)。然后找到第一个 k 使得 S 中的两个数字 x 的 M[x][k]=0。如果没有这样的数字,则尝试至少一个新的连接,如果甚至没有一个数字,那么两个邻居都被完全覆盖,输入一些数字从这里发现 - 可能是“最坏情况”中的一个 - 这样的 x 其中 Sum(M[x][i]) 是最小的。在任何情况下都有多个可供选择的情况下,您还应该选择“最坏情况”中的一个。
- 设置 R[i][j] 的值后,不要忘记用 S - M[R[i][j]][x] = M[x][R[i] 中的数字 x 标记新连接[j]] = 1。
- 如果矩阵已填充且 M 中仍有未标记的连接,则将另一行附加到矩阵并继续。如果在结束之前找到所有连接,则删除多余的行。
你可以检查这个算法,看看会发生什么。第 5 步是玩耍的地方,尤其是在相同情况下猜测选择哪一个(几个数字可能处于同样“最坏情况”)。
例子:
对于 K=6,我们需要 15 个连接:
N=4,我们需要 4x4 方阵。理论说 4x3 矩阵有 17 个连接,所以它可能适合,但我们将尝试 4x4。
这是上述算法的输出:
1234
5615
2413
36**
我不确定您是否可以通过 4x3 完成,也许可以... :)