[问题描述]
给定一个集合A,求A的所有非空子集。例如A={a,b}时,则它的所有非空子集为{a},{b},{a,b}。集合A不空,并且A的元素个数不超过10个。
[输入]
有多组测试数据,每组测试数据为一行。
每行表示一个集合,集合由一对大括号括起来,集合之间的元素用一个逗号隔开。之间没有任何的空白字符。已经知道集合元素按字典顺序排列。
[输出]
每组测试数据输出为2^n-1行,每行表示一个非空子集。子集与子集的顺序参考输出样列。(对应的二进制由小到大)
每个子集的元素按字典顺序排列,元素之间用逗号隔开,没有任何的空白字符。子集由一对大括号括起来。
[输入样列]
{a,b,c}
[输出样例]
{a}
{b}
{a,b}
{c}
{a,c}
{b,c}
{a,b,c}
解题思路:
一开始思路不正确,换了两次思路,写到最后都发现太复杂 ,最后想到了这个方法,耗时将近两个小时:
我发现输出样例很像二进制编码
假设{a}是10000
{b}可以看成是10000+1=01000(从左往右进位,这样方便数组累加)
{a,b}就是01000+1=11000
{c}就是11000+1=00100(也就是说这个二进制数第一位对应a,如果该位是1的话,就要输出a,第二位对应b,以此类推)
这串二进制数最长是26位,对应26个字母
代码如下:
#include<stdio.h>
#include<string.h>
int main(){
char ch[27];
char ch1[81];
int i,j,k,s,flag;
gets(ch1);
s=0;
for(i=0;ch1[i]!='\0';i++){//把字母单独提取出来,存进ch数组中
if(ch1[i]>='a'&&ch1[i]<='z'){
ch[s]=ch1[i];
s++;
}
}
ch[s]='\0';
int sum=1;
for(i=0;i<strlen(ch);i++){//计算一共要输出几行
sum*=2;
}
sum--;
int n=0;
ch[s]='\0';
int cnt[26]={0};//二进制编码串
while(1){
cnt[0]++;
n++;
if(n>sum){
break;
}
for(i=0;i<26;i++){//按照二进制的规则进位
if(cnt[i]>=2){
cnt[i]=0;
cnt[i+1]++;
}
}
printf("{");//把每次进位的结果对应ch数组输出
flag=1;
for(i=0;i<strlen(ch);i++){
if(cnt[i]){
if(flag){
flag=0;
printf("%c",ch[i]);
}
else{
printf(",%c",ch[i]);
}
}
}
printf("}\n");
}
return 0;
}
3130



被折叠的 条评论
为什么被折叠?



