集合的所有分割方式2013年1月28日

       问题描述:分割集合成多个子集合,这几个子集合间没有交集且他们的并集是原集合。

       思路:将包含n个元素的集合set的分割表示为n个数字。比如set[]={1,2,3,4},那么{1,2},{3,4}就可以表示为1122,这4个数分别表示set[0]在第一个分割集合,set[1]在第一个分割集合,set[2]在第二个分割集合,set[3]在第二个分割集合。将这个过程称为编码。

       然后抓住两个要点:

       1.第i个元素的编码一定小于或者等于i。约定一下,set原集合已经从小到大排列好,分割的集合也是这样排好。然后,很容易理解,第1个元素的编码肯定为1。接着,第2个元素如果在第一个分割集合中,那么他的编码也是1;但如果不是在第一个分割集合中,那么第2个元素的编码肯定是2,因为在第二个分割集合中,最小的数最少也是2;依次类推,可以很容易用数学归纳法证明。

       2.第i个元素的编码一定小于等于1,2,3,....i-1这些元素的编码中的最大值再加1。这也很容易想到,也很容易用数学归纳法证明。

       抓住这个要点后,就用深度搜索构造一颗子集合树就可以解决问题了。但是,我在构造子集树的过程中出现了一个思维上的错误,导致浪费了不少调试的时间。具体的错误见代码注释的描述。

       代码如下:

 1 #include <stdio.h>
 2 #define MAX 1000
 3 
 4 int set[MAX]={1,2,3,4};
 5 int n=4;
 6 int code[MAX]={1,1,1,1};
 7 
 8 //prototype
 9 void DFS(int index);
10 
11 void print_set()
12 {
13     int index;
14     int max=-1;
15     printf("{");
16     for(index=0;index<n;index++)
17     {
18         if(code[index]==1) 
19             printf("%d ",set[index]);
20         if(max<code[index])
21             max=code[index];
22     }
23     printf("},{");
24     for(index=2;index<=max;index++)
25     {
26         int index_2; 
27         for(index_2=0;index_2<n;index_2++)
28             if(code[index_2]==index)
29                 printf("%d ",set[index_2]);
30         printf("},{");
31     }
32     printf("\n");
33 }
34 
35 //find out the max code of 1,2,3...i-1 and plus 1
36 int max_pre(int i)
37 {
38     int index;
39     int max=-1;
40     for(index=0;index<i;index++)
41         if(code[index]>max)
42             max=code[index];
43     return (max+1); 
44 }
45 
46 int main()
47 {
48     int i; 
49     DFS(1);
50     return 0;
51 }
52 
53 void DFS(int index)
54 {
55     print_set();
56     if(index==n)
57         return ;
58     for(;index<n;index++)
59     {  
60         int temp=code[index]+1;
61         //在写这里的代码时,我出现了一个思维上的误区:在回溯时我只顾把code[index]++,而没有将code[index]在2到max_pre(index)遍历,这导致了我调试了挺长时间。
62         for(;temp<=index+1 && temp<=max_pre(index);temp++)
63         {
64             int save=code[index];
65             code[index]=temp;
66             DFS(index+1);
67             code[index]=save;
68         }
69 
70     }
71 
72 }

       参考资料:《C语言名题精选百则技巧篇》

       如果你觉得我的文章对你有帮助,请推荐一下,非常感谢!

原文地址:https://www.cnblogs.com/NeilHappy/p/2879725.html