解题报告 :给出n个数,求这n个数的子集的和是否等于一个数,如果是就把这个子集以a+b+c.....的形式输出来。
用增量构造法生成子集,然后判断子集的和是否满足要求,这题要注意要判重,因为给出的这n个数可能有重复的数,所以可能会重复得到某个相同的子集,我的判重方法用的是最暴力的方法,将新生成的子集与已经存在的子集一一进行比较,如果出现相同的则不输出,如果没有相同的则先将这个子集加入到已经出现过的集合中然后再将这个集合输出来。不过这题输入的数据好像是按顺序输出的,所以判重的时候不需要先排序再判,直接判就可以了。

1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 int B[15],t,n,map[10000][15],num,flag; 6 7 int judge(int* A,int m) 8 { 9 int C[15]; 10 for(int i = 1;i<=m;++i) 11 C[i] = B[A[i]]; 12 int sum = 0; 13 for(int i = 1;i<=m;++i) 14 sum += C[i]; 15 if(sum != t) 16 return 0; 17 int k = 1; 18 while(k <= num) 19 { 20 int j = 1; 21 while(j <= map[k][0] && map[k][j] == C[j]) 22 j++; 23 if(j >= map[k][0] + 1) 24 return 0; 25 else k++; 26 } 27 num++; 28 map[num][0] = m; 29 for(int i = 1;i<=m;++i) 30 map[num][i] = C[i]; 31 return 1; 32 } 33 void dfs(int* A,int deep) 34 { 35 if(deep > 1) 36 { 37 if(judge(A,deep-1)) { 38 flag = 1; 39 printf("%d",B[A[1]]); 40 for(int i = 2;i<=deep-1;++i) 41 printf("+%d",B[A[i]]); 42 puts(""); 43 } 44 } 45 int s = deep==1? 1:A[deep-1]+1; 46 for(int i = s;i<=n;++i) 47 { 48 A[deep] = i; 49 dfs(A,deep+1); 50 } 51 } 52 int main() 53 { 54 int A[15]; 55 while(scanf("%d%d",&t,&n),t+n) 56 { 57 for(int i = 1;i<=n;++i) 58 scanf("%d",&B[i]); 59 memset(A,0,sizeof(A)); 60 memset(map,0,sizeof(map)); 61 num = flag = 0; 62 printf("Sums of %d: ",t); 63 dfs(A,1); 64 if(!flag) 65 printf("NONE "); 66 } 67 return 0; 68 }