【UOJ 436】求子集

【题目描述】:
监狱里除了修罗王以外,其他的囚犯都喜欢拉帮结派以壮大势力,但拉帮结派并不是无原则的,而是要看发展对象是不是看上去够顺眼,所谓顺眼,即是发展对象拥有的一些个性特征符合帮派的要求。例如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(")\n"); 
        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('\n');
}
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("()\n");
    //dfs(n,0,"(");
    dfs(0,0,0);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wuhu-JJJ/p/11133645.html