【问题标题】:How to Shuffle an Array with Fixed Row/Column Sum?如何使用固定的行/列总和对数组进行洗牌?
【发布时间】:2013-01-14 13:19:18
【问题描述】:

我需要将随机论文分配给班级的学生,但我有以下限制:

  1. 每个学生应分配两篇论文。
  2. 每篇论文应分配给(大约)相同数量的学生。

是否有一种优雅的方式来生成具有此属性的矩阵?即它被洗牌但行和列的总和是恒定的?举例说明:

Student A   1  0  0  1  1  0 |  3
Student B   1  0  1  0  0  1 |  3
Student C   0  1  1  0  1  0 |  3
Student D   0  1  0  1  0  1 |  3
            ---------------- 
            2  2  2  2  2  2

我想先用正确的行/列总和构建一个“初始矩阵”,然后先随机排列行,然后是列,但是如何生成这个初始矩阵?这里的问题是我将在(例如)以下替代方案之间进行选择,并且有两个学生分配了相同的论文(在左侧设置中)这一事实不会通过行/列改组而改变:

INITIAL (MA):            OR (MB):
A   1  1  1  0  0  0  ||  1  1  1  0  0  0  
B   1  1  1  0  0  0  ||  0  1  1  1  0  0
C   0  0  0  1  1  1  ||  0  0  0  1  1  1
D   0  0  0  1  1  1  ||  1  0  0  0  1  1

我知道我可以想出一些快速/肮脏的东西,并在必要时进行调整,但这似乎是一个有趣的练习。

【问题讨论】:

  • 首先,证明这个命题。令 C 为允许矩阵的集合。 (1) 如果 A 和 B 在 C 中,则存在一系列行/列置换矩阵 P1...Pn 其中 A = P1 P2 ... Pn B。 (2) 如果 B 在 C 中,则对于任何序列行/列置换矩阵 P1...Pn, A = P1 P2 ... Pn B 也在 C 中。由此,您知道初始矩阵是什么并不重要。只需将其设为 n 对角线,角三角形为 1,如示例所示。
  • 这听起来很合理,但你所说的“行/列置换矩阵”是什么意思?在我看来,仅通过改组行和列就无法在我的帖子中从 MA 转到 MB。 IE。总会有两行在相同的地方有 1。我错了吗?
  • 在我看来,在我的帖子中,仅通过随机排列行和列是无法从 MA 转到 MB这意味着你盯着它看的时间不够长。您可以使用某种形式的高斯消元法。对于您的示例,请使用 C = [1 0 0 0; 1 0 0 0;0 0 1 0; 0 0 1 0],然后 C * B = A。
  • 你是对的!但是您的 C不是置换矩阵,因为它在每列中都没有 1?它是否仍然保留行/列总和? (即,您正在从 MB 中“删除”第 2 行和第 4 行)。似乎在纯置换矩阵下 MAMB 属于不同的“组”?
  • 那是因为 A 和 B 不是正方形的。

标签: algorithm math random shuffle


【解决方案1】:

如果你想进行排列,怎么办:

  • 随机选择一个学生,比如学生 1

  • 对于这个学生,随机选择一张他有的论文,比如论文 A

  • 随机选择另一个学生

  • 对于这个学生,随机选择一张他有的论文,比如论文 B(不同于 A)

  • 把试卷 B 给学生 1,把试卷 A 给学生 2。

这样,您既可以保留不同论文的数量,也可以保留每个学生的论文数量。事实上,两个学生都给了一篇论文,并收到了一篇回馈。此外,不会创建或删除任何论文。

就表格而言,这意味着找到两对索引(i1,i2)和(j1,j2)使得A(i1,j1)= 1,A(i2,j2)=1,A(i1, j2)=0 和 A(i2,j1)=0 并且将 0 更改为 1,将 1 更改为 0 => 行和列的总和不会改变。

备注1:如果你不想通过排列进行,你可以简单地将所有纸张放入一个向量(放入2次纸张A,2次纸张B,...)。然后,随机打乱向量并将 k 首先归于第一个学生,将 k 下一个归于学生 2,......但是,您可以以一个学生有多次相同的论文结束。在这种情况下,请从姓氏文件开始进行一些排列。

【讨论】:

  • 您的第一个解决方案似乎不能保证有关列或行总和的任何信息。您的第二个解决方案似乎允许学生两次获得相同的论文,这是不可取的。
  • @Noio:我改变了我的答案,希望现在更清楚了。对于第二种解决方案,对不起,我不明白不允许多篇论文。我对此发表了评论。
  • 啊,听起来不错。在该操作(“交换”)下,我认为问题 中的 MAMB 是等效的。这意味着初始条件无关紧要,所以我可以选择任何东西,然后继续进行许多交换。
  • 是的,MA 和 MB 之间只有一个排列(i1=2,i2=4,j1=1,j2=4)
  • @Noio:这个答案是否满足您的需求?有什么遗漏吗?
【解决方案2】:

您可以按如下方式生成初始矩阵(伪 Python 语法):

column_sum = [0] * n_students

for i in range(n_students):
    if column_sum[i] < max_allowed:
        for j in range(i + 1, n_students):
            if column_sum[j] < max_allowed:
                generate_row_with_ones_at(i, j)
                column_sum[i] += 1
                column_sum[j] += 1

                if n_rows == n_wanted:
                    return

这是对所有 n 的直接迭代,选择 2 个不同的行,但尽可能早地强制执行对列总和的约束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-17
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 2022-09-22
    • 2021-11-28
    • 1970-01-01
    相关资源
    最近更新 更多