我需要为一个班级的学生分配随机论文,但我有以下约束:
是否有优雅方式生成具有此属性的矩阵?即它被洗牌但行和列的总和是不变的?举例说明:
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
我想过首先用正确的行/列总和构建一个“初始矩阵”,然后先随机置换行,然后是列,但是如何生成这个初始矩阵?这里的问题是我会在(例如)以下备选方案之间做出选择,并且有两个学生分配了相同的论文(在左侧设置中)不会改变行/列改组:< / p>
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
我知道我可以提出一些快速/肮脏的东西,并在必要时进行调整,但这似乎是一种有趣的练习。
答案 0 :(得分:1)
您可以按如下方式生成初始矩阵(伪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个不同行的直接迭代,但对列总和的约束尽早实施。
答案 1 :(得分: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并且将0s改变1s并且将0s改变为0s =&gt;行和列的总和不会改变。
备注1:如果你不想按排列进行处理,你可以简单地将所有纸张放入一个矢量(放2张纸A,2张纸B,......)。然后,随机改变矢量并将k首先归属于第一个学生,将k个接下来归属于学生2,......但是,您可以以具有多次相同纸张的学生结束。在这种情况下,从外部论文开始做一些排列。