從集合中枚舉子集有許多種情況。這里集合是指廣義的,它可能包含相同的元素。先討論不含相同元素的集合,枚舉問題規定如下:從N個元素的集合中,取出R個的元素子集。根據子集的不同性質可分為:
一,子集是否可以重復包含某元素
二,子集的元素是否有序。
上面兩種情況自由組合可分為4種情形,見下表:
條件一
條件二
可以重復包含
有序
1
無序
2
不可重復包含
3
4
表一
例1:按照這4種情況,枚舉集合{a,b,c},其中R=2。
情況1:有{a,a},{a,b},{a,c},{b,a},{b,b},{b,c},{c,a},{c,b},{c,c}9種。
情況2:有{a,a},{b,b},{c,c},{a,b},{a,c},{b,a}6種。
情況3:有{a,b},{a,c},{b,a},{b,c},{c,a},{c,b}6種。
情況4:有{a,b},{a,c},{b,a}3種。
下面討集合包含相同元素,這里的相同元素視為完全等同,可以替換。這樣集合含有兩個信息,一是含有N各不同的元素,二是每種元素有多少個。如果每種元素的個數為1,就是上面討論的情況。這里增加了新的討論條件,子集重復包含某元素的個數是否可以超過集合中該元素的個數。上一種情況,重復包含就意味超過。而在這里,就要分情況處理。
可以重復包含,可以超過
可以重復包含,不可以超過
5
6
表二
例2:按照這6種情況,枚舉集合{a,a,b,c},其中R=2。
情況5:有{a,a},{a,b},{a,c},{b,a},{b,c},{c,a},{c,b}7種。
情況6:有{a,a},{a,b},{a,c},{b,a}4種。
比較例1和例2發現情況1,2,3,4結果一樣,其實在可以超過的條件下,集合某個元素的個數是不起限制作用,結果也就一樣。所以可合并這兩種情況。從分析中知道,枚舉這樣的集合需要知道兩類信息。N種不同的元素和每種元素的個數。N種不同的元素可以映射到0至(N-1)N整數上。問題就變成了枚舉N個整數。枚舉出來的數字可以映射到原先的元素。N和表示每種元素個數的數組就是需要的信息。
枚舉R個元素就是取R個數,每個數的取值0至(N-1)。這樣每個子集對應一個R位N進制的數。于是枚舉數從0到NR-1,就枚舉出每種可能的子集,然后判斷子集是否滿足條件。
下面分別討論這六種情況如何判斷。
情況1:每個枚舉數都滿足要求。
情況2:枚舉數高位的數字不大于低位的數字。
情況3:枚舉數的各位數字不能相同。
情況4:枚舉數高位的數字小于低位的數字。
情況5:數字在枚舉數出現的次數不能超過該數字對應元素的個數。
情況6:情況5加上情況2。
其他實現見代碼。
代碼編譯方式:
g++ SetIter.cpp -D_SETITER_TEST_ 編譯,運行。可看到例1的結果,
g++ SetIter.cpp -D_SETITERAGENT_TEST_ 編譯,運行,就可以看到例2的結果。
posted on 2007-11-03 12:36 lemene 閱讀(2287) 評論(0) 編輯 收藏 引用
Powered by: C++博客 Copyright © lemene