|
重新写了一下代码,附件中的源数据是经过修改了的,为了便于测试。
优点:
1、确保不重复。
2、确保占用最少的宿舍,占用宿舍的多少不仅与总人数有关,也与每校的人数有关,比如附件中男生是86人,按6人算的话应该是15个宿舍,但情况并非如此,因为K学校有34个人,所以必须占用34个宿舍。
3、代码从上到下顺序运行,没有交叉,各单元有自己的功能,易于理解。
4、单元格操作少,因此速度较快,但有较多的无用循环,因为图写代码简单,也就没有管它。
缺点:
1、没有做到只有一个宿舍不满6人,这种要求有时候可以实现,有时候根本无法实现,如果人数都集中在一两个学校不足6人的宿舍会很多,如果保证占用最少的宿舍,不满6人何妨?也许会说,虽然不能做到只有一个宿舍不满6人,但可做到最大限度的满6人,这应该可以做到,但我不会,等高手。
2、同校学生排在了相邻的的宿舍,这也没什么,比如K校有34人,必定都排在相邻的宿舍,如果需要,可以用随机函数把它打乱。
一定会有漏洞存在,请测试的朋友指出来。
Sub test()
Dim ar1, ar2, cr(), br(), xb, r&, n&, s, i&, j&, k&, x&, d, rs&, rm&, t
t = Timer
Set d = CreateObject("scripting.dictionary")
Sheet2.Cells.Clear
ar1 = Sheet1.[a1].CurrentRegion
ar2 = ar1
r = UBound(ar1)
ReDim cr(2 To r)
For i = 2 To r
cr(i) = i
Next i
For i = 2 To r
n = Int(Rnd() * (r - i + 1)) + i
s = cr(i)
cr(i) = cr(n)
cr(n) = s
Next i
For i = 2 To r
For j = 1 To 4
ar2(i, j) = ar1(cr(i), j)
Next j
Next i
xb = Array("男", "女")
For x = 0 To 1
n = 0: rs = 0: rm = 0
ReDim ar1(1 To r, 1 To r)
For i = 2 To r
If ar2(i, 4) = xb(x) Then
rs = rs + 1
If d.exists(ar2(i, 3)) = 0 Then
n = n + 1
d(ar2(i, 3)) = n
ar1(n, i) = ar2(i, 3) & ar2(i, 2)
Else
ar1(d(ar2(i, 3)), i) = ar2(i, 3) & ar2(i, 2)
End If
End If
Next i
d.RemoveAll
ReDim cr(1 To r * 6)
k = 0
For i = 1 To n
s = 0
For j = 1 To r
If ar1(i, j) <> "" Then
k = k + 1
cr(k) = ar1(i, j)
s = s + 1
End If
Next j
If rm < s Then rm = s
Next i
If Int((rs - 1) / 6) + 1 > rm Then rm = Int((rs - 1) / 6) + 1
ReDim br(1 To rm, 1 To 7)
For i = 1 To rm
br(i, 1) = xb(x) & "舍_" & i
For j = 2 To 7
br(i, j) = cr((j - 2) * rm + i)
Next j
Next i
Sheet2.[a65536].End(3).Offset(1).Resize(rm, 7) = br
Next x
MsgBox Format(Timer - t, "0.000")
End Sub
|
|