【题目描述】:
监狱里除了修罗王以外,其他的囚犯都喜欢拉帮结派以壮大势力,但拉帮结派并不是无原则的,而是要看发展对象是不是看上去够顺眼,所谓顺眼,即是发展对象拥有的一些个性特征符合帮派的要求。例如N=3,表示符合帮派的个性特性共有3个,假设以a、b、c定义,我们称(a,b,c)为集合S,而发展对象只要拥有其中的一个或多个特征都会被帮派选中,即符合子集(S)={(),(a),(b),(c),(a,b),(b,c),(a,c),(a,b,c)}中的任何一个均可。当然,你可能要问了,这空集没有任何特征也符合条件?对啊,“和光同尘”也是一种很受大家欢迎的生活态度啊。
现输入N,求(S)的子集。
【输入描述】:
一个整数即N。
【输出描述】:
按字典序输出所有子集,每个子集占一行。
【样例输入】:
3
【样例输出】:
()
(a)
(ab)
(abc)
(ac)
(b)
(bc)
(c)
【时间限制、数据范围及描述】:
时间:1s 空间:64M
30%的数据:N<=6
50%的数据:N<=15
100%的数据:0<=N<=21
题解:几天前的题目哈,今天也补上!开始的思路:暴力dfs枚举,每次加进一个字符就和前面的all字符串相比较去重。不过能a掉70分。满分思路:“建树”,左子树:选这个字母。右子树:不选这个字母。然后层层递归,只打印左儿子。右儿子不打印,否则会重复。例如(第一层字母为a,第二为b……)
代码(注释掉的部分是一开始的思路)
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cstdlib> #include<cmath> using namespace std; int n,t=1; /*bool pd(string ss,char cc){ int p=ss.size(); for(int i=1;i<p;i++) if(cc<=ss[i]) return 0; return 1; } void dfs(int k,int num,string s){ if(num==k) return; for(int i=1;i<=n;i++){ char h='a'+i-1; if(pd(s,h)==0) continue; cout<<s+h; printf(") "); dfs(k,num+1,s+h); } } */ char s[125]; void jjj(int l){ putchar('('); for(int i=0;i<l;i++) putchar(s[i]); putchar(')'); putchar(' '); } void dfs(int h, int k,int l){ //每一层该字母:左树选择,右树不选择 if(!k) jjj(l);//右字树不打印 if(h==n) return; s[l]='a'+h; dfs(h+1,0,l+1); dfs(h+1,1,l); } int main(){ scanf("%d",&n); //printf("() "); //dfs(n,0,"("); dfs(0,0,0); return 0; }