代码改变世界

【递归学习ing】幂集问题

2014-11-11 10:51  程序羊_宅在宿舍sicily  阅读(736)  评论(0)    收藏  举报
Description

 我们先看百度百科对幂集的定义:

所谓幂集(Power Set), 就是原集合中所有的子集(包括全集和空集)构成的集族。

我们这个题的任务就是将一个集合的幂集解出来。

我们假设原始集合是一个由数字组成的集合,并且是从1~N的连续整数。

输入一个N,则这个集合的内容是{1, 2, 3, ……, N}。

求解幂集之后按照一定的顺序输出出来,这个顺序是这样的:

对于一个集合,我们将集合内的元素按照从大到小排序。

对于两个集合之间,我们按照从小到大排序,如何比较两个集合之间的大小关系呢?

先从左往右比较集合的元素,哪个集合先遇到大于另一个集合的数字,则说明比它大,如果注意空比任何数字都要小,比如:

{2} < {2, 1}

{1} < {2}

{3, 1} < {3, 2}

Input

 第一行只有一个整数m,代表有m个测试用例

接下来有m行,每一行是一个测试用例,每个测试用例一个整数,代表N的值(0 < N < 15)。

Output

 对于每个用例,输出它的幂集,幂集中的每个集合都占一行,并且没有空格。

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 }
View Code

之后我还想过不用递归的话能不能做,然后我就模拟了递归的过程,因为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 }
View Code

 

 还有一种做法是用二叉树然后前序遍历,但是这种方法用递归实现就可以了,代码没有上面递归的简洁,所以就不贴上来了。