我需要随机生成一个 NxN 整数矩阵,范围在 1 到 K 之间,这样所有行和列都分别具有它们的元素成对不同的属性。
例如对于 N=2 和 K=3
还行吧:
1 2
2 1
这不是:
1 3
1 2
(请注意,如果 K < N 这是不可能的)
当 K 比 N 足够大时,一个足够有效的算法就是生成一个由 1..K 个整数组成的随机矩阵,检查每一行和每一列是否成对不同,如果不是再试一次。
但是如果 K 比 N 大不了多少呢?
这不是一个完整的答案,而是一个关于不起作用的直观解决方案的警告。我假设“随机生成”是指在所有现有此类矩阵上具有统一概率。
对于 N=2 和 K=3,这里是可能的矩阵,直到集合 [1..K] 的排列:
1 2 1 2 1 2
2 1 2 3 3 1
(因为我们忽略了集合 [1..K] 的排列,我们可以假设 wlog 的第一行是1 2
)。
现在,一种直观(但不正确)的策略是逐个绘制矩阵条目,确保每个条目与同一行或列上的其他条目不同。要了解它为什么不正确,请考虑我们已经绘制了这个:
1 2
x .
我们现在正在绘制 x。x 可以是 2 或 3,但如果我们给每个可能性 1/2 的概率,那么矩阵
1 2
3 1
最后会得到 1/2 的概率,而它应该只有 1/3 的概率。
这是一个(文本)解决方案。我不认为它提供了很好的随机性,但无论如何它对您的应用程序来说可能没问题。
让我们使用以下算法在 [0;K-1] 范围内生成一个矩阵(如果您愿意,您将对所有元素执行 +1):
所有算法都基于具有我提到的属性的随机生成器。通过快速搜索,我发现Inversive congruential generator满足此要求。这似乎很容易实现。如果 K 是素数,则有效;如果 K 不是素数,请参见同一页上的“复合逆生成器”。也许处理完美的平方或立方数会有点棘手(你的问题听起来像数独 :-)),但我认为通过创建具有 K 的素数和不同参数化的复合生成器是可能的。对于所有生成器,每列的第一个元素是种子。
无论 K 的值是多少,复杂度仅取决于 N,并且为 O(N^2)。
让我们展示置换行(即取出整行并以某种顺序从它们中组装一个新矩阵,每行可能处于不同的垂直位置)使行和列的所需属性保持不变,假设它们之前是正确的。同样的推理也适用于列排列,以及任何一种排列的任何序列。
我不确定该算法是否能够生成所有可能的满足矩阵,或者如果可以,它是否会以相等的概率生成所有可能的满足矩阵。另一个我没有答案的有趣问题是:需要多少轮行排列然后列排列?更准确地说,是否有任何有限的 row-perm-then-column-perm 轮次序列等效于有限数量的(或特别是一个)row-perm-then-column-perm 轮次?如果是这样,那么在第一行和第一列排列之后的进一步排列不会获得任何东西。也许有较强数学背景的人可以发表评论。但无论如何它可能已经足够好了。