题目:求集合的所有子集

题解
  1. 天坑的一道题,样例根本体现不了具体的输出顺序。
  2. 这里代码1的思路是初始创建一个空的字符数组,然后依次向里面加元素,在加入元素的时候将该数组的子集按长度递增的顺序依次与待加入元素结合后输出。
  3. 代码2则是迭代的思想,即根据n-1的子集得到n的子集。然后另外一个坑又来了,这里并不是直接在n-1的所有子集后面加上第n个元素得到n的子集,而是要先将n-1的子集按照长度递增的顺序排列后再加上第n个元素,所以一开始很难看出来是迭代的顺序。。。
  4. 最后附上n=5时代码1和代码2的输出。
题目
问题 A: 求集合的所有子集(数组)
时间限制: 1 Sec  内存限制: 128 MB
提交: 390  解决: 96
[提交][状态][讨论版]
题目描述
一个元素个数为n(n>0)的集合,有2n个子集(包括空集)。例如,集合A={a,b,c}的子集有23=8个,分别为:{}(空集){a}{b}{a、b}{c}{a,c}{b,c}{a,b,c}。

输入一集合(假设集合元素为字符),给出该集合的所有子集。子集的输出顺序根据样例输出分析得出。

输入
测试次数t

每组测试数据格式为:集合元素个数n,后跟集合的n个元素。

输出
对每组测试数据,输出子集个数,后面每行一个子集,输出所有子集。每组测试数据之间以一个空行分隔。

样例输入
2
3
a b c
4
e f a d
样例输出
8
{}
{a}
{b}
{a,b}
{c}
{a,c}
{b,c}
{a,b,c}

16
{}
{e}
{f}
{e,f}
{a}
{e,a}
{f,a}
{e,f,a}
{d}
{e,d}
{f,d}
{a,d}
{e,f,d}
{e,a,d}
{f,a,d}
{e,f,a,d}
代码1(错50%)
#include <stdio.h>

int main(void)
{
    int i, j, k, t;
    scanf("%d", &t);
    while(t--)
    {
        int n;
        scanf("%d", &n);
        getchar();
        char a[n];
        for(i=0; i<n; i++)
            scanf(" %c", &a[i]);//注意读取前面多个空格来吃掉空白符
        char b[n];
        int num = 1;
        for(i=0; i<n; i++)
            num *= 2;
        printf("%d\n", num);
        printf("{}\n");
        for(i=0; i<n; i++)
        {
            printf("{%c}\n", a[i]);
            for(j=0; j<i; j++)
            {
                int temp[j+1];
                for(k=0; k<=j; k++)
                    temp[k] = k;
                int pos = j;
                printf("{");
                for(k=0; k<=j; k++)
                    printf("%c,", b[temp[k]]);
                printf("%c}\n", a[i]);
                while(temp[0]!=i-j-1)
                {
                    if(pos>0 && temp[pos]==i-j+pos-1)
                    {
                        int v = pos-1;
                        while(temp[v]==i-j+v-1)
                            v--;
                        temp[v]++;
                        for(k=v; k<j; k++)
                            temp[k+1] = temp[k]+1;
                    }
                    else
                        temp[pos]++;
                    printf("{");
                    for(k=0; k<=j; k++)
                        printf("%c,", b[temp[k]]);
                    printf("%c}\n", a[i]);
                }
            }
            b[i] = a[i];
        }
        printf("\n");
    }
}
代码2(AC)
#include <stdio.h>

int main(void)
{
    int i, j, k, l, t;
    scanf("%d", &t);
    while(t--)
    {
        int n;
        scanf("%d", &n);
        char a[10000][100];
        a[0][0] = 0;
        int num = 1;
        for(i=0; i<n; i++)
        {
            char ch;
            scanf(" %c", &ch);
            int temp = num;
            for(j=0; j<=i; j++)
            {//变量j实现对原子集的按长度排序
                for(k=0; k<num; k++)
                {
                    if(a[k][0]==j)
                    {//同上
                        for(l=1; l<=a[k][0]; l++)
                            a[temp][l] = a[k][l];
                        a[temp][0] = a[k][0]+1;
                        a[temp][l] = ch;
                        temp++;
                    }
                }
            }
            num *= 2;
        }
        int temp = 1;
        for(i=0; i<n; i++)
            temp *= 2;
        printf("%d\n", temp);
        for(i=0; i<num; i++)
        {
            printf("{");
            for(j=1; j<=a[i][0]; j++)
            {
                if(j!=a[i][0])
                    printf("%c,", a[i][j]);
                else
                    printf("%c", a[i][j]);
            }
            printf("}\n");
        }
        printf("\n");
    }
}
  • 代码1

在这里插入图片描述

  • 代码2

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值