|
楼主 |
发表于 2018-1-2 16:21
|
显示全部楼层
全部代码
- 'P106:特殊的子集和: 元检验
- '
- '记S(A)是大小为n的集合A中所有元素的和。若任取A的任意两个非空且不相交的子集B和C都满足下列条件,我们称A是一个特殊的和集:'
- 'S(B) ≠ S(C);也就是说,任意子集的和不相同。
- '如果B中的元素比C多,则S(B) > S(C)。
- '在这个问题中我们假定集合中包含有n个严格单调递增的元素,并且已知其满足第二个条件。'
- '令人惊奇的是,当n = 4时,在所有可能的25组子集对中只有1组需要检验子集和是否相等(第一个条件)。同样地,当n = 7时,在所有可能的966组子集对中只有70组需要检验。'
- '当n = 12时,在所有可能的261625组子集对中有多少组需要检验?
- '分析:
- 'n=4,考察2p2的情况,只有(14,23)。。。。。1种
- 'n=5,也只需考察2p2的情况,有C(5,4)*1=5种
- 'n=6, 考察2p2的情况,有C(6,4)*1=15种
- ' 3P3的情况,有(156,234),(146,235),(136,245),(126,345),(145,236) 5种
- ' 共计20种
- 'n=7, 考察2p2的情况,有C(7,4)*1=35种
- ' 3P3的情况,有C(7,6)*5=35种
- ' 共计70种?
- '可令f(n,m)为n个元素的集合,考察mPm的情形
- ' f(n, m) = c(n , 2 * m) * g(2*m, m),其中g(2m,m)为2m个元素中需考察mPm的个数
- '只要能计算出g(2*m,m)的个数,那么可以推导也所有f
- Dim brr, t
- Sub problem106()
- n = 12
- For m = 2 To n / 2
- ' res = res + Application.combin(n, 2 * m) * g(2 * m, m)
- res = res + Application.combin(n, 2 * m) * g(m)
- Next
- Debug.Print res
- End Sub
- Function g(n) '2n个数中选n-n需比对的个数 初始数组arr,返回brr,n为选取个数
- t = 0
- ReDim arr(2 * n - 1)
- For k = 1 To 2 * n
- arr(k - 1) = k
- Next
- 'arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
- 'n = (UBound(arr) + 1) / 2
- ReDim result(0 To UBound(arr))
- ReDim brr(1 To Application.combin(UBound(arr) + 1, n)) '结果的个数
- Call Cmbine(arr, 0, result, n, n, UBound(arr) + 1) '用递归生成数组brr,为集合arr取n个的所有组合,首尾相对
- For i = 1 To UBound(brr) / 2
- s1 = Split(brr(i), ","): s2 = Split(brr(UBound(brr) - i + 1), ",") '首尾两两配对
- tmp = 0
- For t = 1 To UBound(s1)
- a = Val(s1(t)): b = Val(s2(t))
- tmp = tmp + Sgn(a - b) 'sgn:符号函数,正数为1,负数为-1
- Next
- If Abs(tmp) < n Then res = res + 1 '关键句:两个集合B,C,如果不是B所有元素都大于或小于C所有元素,那么需要检验
- Next
- g = res
- End Function
- '//arr为原始数组
- '//start为遍历起始位置
- '//result保存结果,为一维数组
- '//count为result数组的索引值,起辅助作用
- '//NUM为要选取的元素个数
- '//arr_len为原始数组的长度,为定值
- Sub Cmbine(arr, start, result, count, NUM, arr_len)
- i = 0
- For i = start To arr_len + 1 - count - 1
- result(count - 1) = i
- If count - 1 = 0 Then
- For j = NUM - 1 To 0 Step -1
- s = s & "," & arr(result(j))
- Next
- t = t + 1
- brr(t) = s: s = ""
- Else
- Call Cmbine(arr, i + 1, result, count - 1, NUM, arr_len)
- End If
- Next
- End Sub
复制代码 |
|