【递归学习ing】幂集问题
2014-11-11 10:51 程序羊_宅在宿舍sicily 阅读(736) 评论(0) 收藏 举报我们先看百度百科对幂集的定义:
所谓幂集(Power Set), 就是原集合中所有的子集(包括全集和空集)构成的集族。
我们这个题的任务就是将一个集合的幂集解出来。
我们假设原始集合是一个由数字组成的集合,并且是从1~N的连续整数。
输入一个N,则这个集合的内容是{1, 2, 3, ……, N}。
求解幂集之后按照一定的顺序输出出来,这个顺序是这样的:
对于一个集合,我们将集合内的元素按照从大到小排序。
对于两个集合之间,我们按照从小到大排序,如何比较两个集合之间的大小关系呢?
先从左往右比较集合的元素,哪个集合先遇到大于另一个集合的数字,则说明比它大,如果注意空比任何数字都要小,比如:
{2} < {2, 1}
{1} < {2}
{3, 1} < {3, 2}
第一行只有一个整数m,代表有m个测试用例
接下来有m行,每一行是一个测试用例,每个测试用例一个整数,代表N的值(0 < N < 15)。
对于每个用例,输出它的幂集,幂集中的每个集合都占一行,并且没有空格。
sample input:
2 1 3
sample output:
{}
{1}
{}
{1}
{2}
{2,1}
{3}
{3,1}
{3,2}
{3,2,1}
这道题用递归做的话非常的简洁,我们可以考虑去或者不取,核心代码只需要3行就ok了。不如对于N= 3,那么我们先考虑是否取3,那么递归树的第一层就会出现0 和 3。第二层为0 2 3 (3,2)。第三层为
0 1 2 (2,1) 3 (3,1) (3,2) (3,2,1),然后我们顺序输出就可以了(不会画图大家凑合着看吧)
所以直接上代码:
1 #include <iostream> 2 #include <vector> 3 #include <cstdlib> 4 using namespace std; 5 6 void print(vector<int> a) { 7 cout << "{"; 8 int size = a.size(); 9 for (int i = 0; i < size - 1; i++) { 10 cout << a[i] << ","; 11 } 12 if (size != 0) 13 cout << a[size - 1]; 14 cout << "}\n"; 15 } 16 17 void solve(int n, vector<int> a) { 18 if (n == 0) print(a); 19 else { 20 solve(n - 1, a); 21 a.push_back(n); 22 solve(n - 1, a); 23 } 24 } 25 26 int main() { 27 int t; 28 cin >> t; 29 while (t--) { 30 int n; 31 cin >> n; 32 vector<int> a; 33 solve(n, a); 34 } 35 // system("pause"); 36 }
之后我还想过不用递归的话能不能做,然后我就模拟了递归的过程,因为N最大为14,所以我申请了一个2^14的字符串数组来存所有可能的情况。对于每个N,我们输出数组中0到2^N-1的情况(直接打表输出)。然后每次当N+1时,其实就是保持前面数组不变,然后在令前面的2^N个字符串数组中加入“N+1”。比如说,我们已经知道1的时候是{}和{1},那么对于2的情况,我们保存{}和{1},然后再在{}和{1}中加入2,所以2的情况就是{}{1}{2}{2,1}。
代码如下:
1 #include <iostream> 2 #include <string> 3 #include <cmath> 4 #include <cstdlib> 5 using namespace std; 6 string str[32767]; 7 static long int co; 8 void print() { 9 for (int i = 0; i < co; i++) { 10 string s = str[i]; 11 int size = s.size(); 12 cout << "{"; 13 for (int j = 0; j < size; j++) { 14 if (s[j] == '0') break; 15 if (s[j + 1] == '0') { 16 cout << s[j]; 17 break; 18 } 19 else { 20 if (s[j] == 'A') cout << "10,"; 21 else if (s[j] == 'B') cout << "11,"; 22 else if (s[j] == 'C') cout << "12,"; 23 else if (s[j] == 'D') cout << "13,"; 24 else if (s[j] == 'E') cout << "14,"; 25 else cout << s[j] << ","; 26 } 27 } 28 cout << "}\n"; 29 } 30 } 31 32 //void print1() { 33 //for (int i = 0; i < co; i++) { 34 //string s = str[i]; 35 //cout << s << endl; 36 //} 37 //} 38 39 void pow_s(int n, long int x) { 40 if (n == 0) { 41 str[co++].push_back(n + '0'); 42 return; 43 } 44 else { 45 pow_s(n - 1, x); 46 int c = co;; 47 for (int j = 0; j < c; j++) { 48 if (n <= 9) 49 str[co].push_back(n + '0'); 50 else if (n == 10) str[co].push_back('A'); 51 else if (n == 11) str[co].push_back('B'); 52 else if (n == 12) str[co].push_back('C'); 53 else if (n == 13) str[co].push_back('D'); 54 else if (n == 14) str[co].push_back('E'); 55 str[co] += str[j]; 56 co++; 57 } 58 } 59 if (co == x) { 60 print(); 61 return; 62 } 63 } 64 65 int main() { 66 int m; 67 cin >> m; 68 while(m--) { 69 int n; 70 cin >> n; 71 if (n == 0) { 72 cout << "{}\n"; 73 } 74 else { 75 for (int i = 0; i < n; i++) { 76 str[i] = ""; 77 } 78 long int x; 79 x = (long)pow((double)2,(double)n); 80 co = 0; 81 pow_s(n, x); 82 for (int i = 0; i < n; i++) { 83 str[i] = ""; 84 } 85 } 86 } 87 system("pause"); 88 }
还有一种做法是用二叉树然后前序遍历,但是这种方法用递归实现就可以了,代码没有上面递归的简洁,所以就不贴上来了。
浙公网安备 33010602011771号