|
完整的代码:
不需要用字典,但是我是用字典统计、观察之后,才算彻底明白怎么回事的。
之前只检查1221或2112的状态,是不准确的。
例如 112212 就能组成3个【1<2对子】最后组合结果肯定是1<2的。所以之前的计算结果偏大了。
- Dim ar(), dic, k&, k1&, m&, n&, tms#
- Sub test() 'by kagawa 2018/1/1
- tms = Timer
-
- For m = 4 To 12
- ReDim ar(1 To m)
- ' Set dic = CreateObject("Scripting.Dictionary")
- k = 0: k1 = 0
- For n = 2 To Int(m / 2)
- Call dgZH(0, 1) '调用组合递归 列出S(B)个数等于S(C)的组合 检查是否可能相等(含1221或2112顺序)
- Next
- ' [a1].Resize(dic.Count) = WorksheetFunction.Transpose(dic.keys)
- Debug.Print m; k; k1
- Next
- Debug.Print Format(Timer - tms, "0.000s")
- MsgBox Format(Timer - tms, "0.000s") & vbCr & m & vbCr & k & vbCr & k1
- End Sub
- Sub dgZH(i1&, t&) '生成个数较少的S(C)组合
- Dim i&, i2&
- For i = i1 + 1 To m - n + t
- ar(i) = 1 '在ar数组记录该元素已被S(C)使用
- If t < n Then
- Call dgZH(i, t + 1)
- Else
- For i2 = 1 To m
- If ar(i2) = 1 Then Exit For '仅需检查C组开始以后的元素组合
- Next
- Call dgZH2(i2, 1) '调用生成S(B)组合的递归
- End If
- ar(i) = ""
- Next
- End Sub
- Sub dgZH2(i2&, t&) '生成个数较多的S(B)组合
- Dim i&, s$, ss$
- For i = i2 + 1 To m - n + t
- If ar(i) = "" Then '检查是否未被S(C)使用
- ar(i) = 2 '在ar数组记录该组合
- If t < n Then
- Call dgZH2(i, t + 1)
- Else
- k = k + 1 '36828
- s = Join(ar, "")
- If f(s) Then k1 = k1 + 1
- ' dic(s) = ""
- ' If InStr(s, "1221") + InStr(s, "2112") Then k1 = k1 + 1 '21605
- End If
- ar(i) = ""
- End If
- Next
- End Sub
- Function f(s) As Boolean '检查12对子的排列情况
- Do
- j1 = InStr(j1 + 1, s, "1")
- If j1 = 0 Then Exit Function '没有新的12对子了
-
- If j2 < j1 Then j2 = j1 '只检查比1更大一些的2成为1组12对子
- j2 = InStr(j2 + 1, s, "2")
- Loop Until j2 = 0 '找不到比上个1更大的2时 就产生1221类型的相等可能性
- f = True
- End Function
复制代码 |
|