10 个解决方案
#1
#include <stdio.h>
#define MAX 20
int results[MAX];
int step;
int numcomb;
void output()
{
int i;
for (i = 0; i < numcomb; i++)
{
printf("%3d", results[i]);
}
printf("\n");
}
void work(int lowerlimit, int upperlimit, int num)
{
int i;
for (i = lowerlimit; i <= upperlimit - num; i++)
{
results[step++] = i;
if (num > 1)
work(i + 1, upperlimit, num - 1);
if (step >= numcomb)
{
output();
}
step--;
}
}
void comb(int n, int m)
{
step = 0;
numcomb = m;
work(0, n, numcomb);
}
void subset(int n)
{
int i;
for (i = 1; i <= n; i++)
{
comb(n, i);
}
}
int main(void)
{
int n;
printf("Please input a integer between 1 and %d: ", MAX);
scanf("%d", &n);
if (n <= 0 || n > MAX)
{
printf("Input error.\n");
return 1;
}
subset(n);
return 0;
}
#2
所有子集。。。。。
输出MAX_N=5的情况:
0
1
2
3
4
0 1
0 2
0 3
0 4
1 2
1 3
1 4
2 3
2 4
3 4
0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
0 1 2 3
0 1 2 4
0 1 3 4
0 2 3 4
1 2 3 4
0 1 2 3 4
total group = 31
#include <stdio.h>
#define MAX_N 5
int g_arr[MAX_N] = {0};
__int64 g_cnt = 0;
void Recur(int* arr, int arr_size, int req_cnt)
{
if (req_cnt > 0)
{
//数据没有选够,从剩下的数据中继续选
//先选中最小的
arr[0] = 1;
//然后从剩下的arr_size - 1个数据中选req_cnt-1个数据
Recur(arr+1, arr_size - 1, req_cnt-1);
//回溯一下,跳过刚才选的那个最小数的情况
arr[0] = 0;
if ((arr_size - 1) >= (req_cnt ))
{
Recur(arr+1, arr_size - 1, req_cnt);
}
}
else
{
//找到一组完整数据
++g_cnt;
//输出组合
for(int i=0; i<MAX_N; i++)
{
if (g_arr[i] == 1)
{
printf("%d\t", i);
}
}
printf("\n");
}
}
int main(int argc, char* argv[])
{
for(int i=1; i<=MAX_N; i++)
Recur(g_arr, MAX_N, i);
printf("total group = %I64u\n", g_cnt);
return 0;
}
输出MAX_N=5的情况:
0
1
2
3
4
0 1
0 2
0 3
0 4
1 2
1 3
1 4
2 3
2 4
3 4
0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
0 1 2 3
0 1 2 4
0 1 3 4
0 2 3 4
1 2 3 4
0 1 2 3 4
total group = 31
#3
我还是先想到递归,因为这个问题等价于输出一个n层二叉树的所有叶子节点。
#4
#include <stdio.h>
#include <string.h>
#include <windows.h>
int a[16]={0};
unsigned long c[16]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
int b[16]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int huanerjinzhi(long d)
{
int i=0;
int count=1;int k=d;
int *p;p=a;
unsigned long *q;q=c;
memset(a,0,sizeof(int)*16);
if(!k) {return 0;}
else {while(k&=(k-1)){count++;}}
while(d)
{
if(d&(*q)){*p=1;d&=~(*q);p++;q++;}
else{*p=0;p++;q++;}
}
return count;
}
void jisuan(long n)
{
long i, j, t;
long r;
long k=(1<<n);
for(i=0;i<k;i++)
{
t=huanerjinzhi(i);
printf("{");
for(r=1,j=0;r<=t;j++)
if(a[j]==1){
if(r!=t)printf("%d,",b[j]);
else printf("%d",b[j]);r++;}
printf("}\n");
}
}
void main()
{
int n;
printf("input a number:\n");
scanf("%d", &n);
long lBegin = GetTickCount();
jisuan(n);
long lEnd = GetTickCount();
printf("%d\n",lEnd-lBegin);
}
#5
输出结果 n=5时
input a number:
5
{}
{1}
{2}
{1,2}
{3}
{1,3}
{2,3}
{1,2,3}
{4}
{1,4}
{2,4}
{1,2,4}
{3,4}
{1,3,4}
{2,3,4}
{1,2,3,4}
{5}
{1,5}
{2,5}
{1,2,5}
{3,5}
{1,3,5}
{2,3,5}
{1,2,3,5}
{4,5}
{1,4,5}
{2,4,5}
{1,2,4,5}
{3,4,5}
{1,3,4,5}
{2,3,4,5}
{1,2,3,4,5}
16
Press any key to continue
#6
//顺序反的...
#include <stdio.h>
#include <stdlib.h>
int zuoyi(int n)
{
int i = 1<<n;
return i-1;
}
int main()
{
int k[100];
int p = 0, q,i,j;
int n;
scanf("%d",&n);
p = zuoyi(n);
for ( i = 0; i <= p; i++ )
{
j = i;
for ( q = 0; j > 0; q++ )
{
k[q] = j%2;
j = j/2;
}
printf(" { ");
while (q--)
{
if ( k[q] ) printf("%d ",q+1);
}
printf("}\n");
}
return 0;
}
#7
谢谢你们,真的好强啊,不知道我什么时候才能达到你们的水平!
好像有一点问题,比如我测试二楼朋友的程序,令MAX_N=10,结果total group是1023没错,可是集合不全啊,是我的显示有问题吗?还是别的原因,如第一项为{023789}而没有小于它的项了
好像有一点问题,比如我测试二楼朋友的程序,令MAX_N=10,结果total group是1023没错,可是集合不全啊,是我的显示有问题吗?还是别的原因,如第一项为{023789}而没有小于它的项了
#8
RE: 7楼
输出数量超出了可显示的上限。
把它重定向到文件中看
比如:
myprog.exe > out.txt
输出数量超出了可显示的上限。
把它重定向到文件中看
比如:
myprog.exe > out.txt
#9
#define Max 20
main()
{
int a[Max] = {0}, b[Max] = {0};
int i, j, m, n, k;
scanf( "%d", &k);
for(i = 1; i < k, i++)
scanf("%d", b[Max]);
m = k;
n = 2 << k;
for(i = 0; i < n; i++)
{
while(k >= 0 || a[k] == 0)
k = k - 1;
if(a[k] == 1 )
{
a[k] = 0;
for(j = k; j > m; j++)
a[j] = 0;
}
for(j = 0; j < m; j++)
{
if(a[j] == 1)
printf(" %d", b[j]);
}
printf("\n");
}
printf("{ }\n");
getch();
}
看看这个对不对?
main()
{
int a[Max] = {0}, b[Max] = {0};
int i, j, m, n, k;
scanf( "%d", &k);
for(i = 1; i < k, i++)
scanf("%d", b[Max]);
m = k;
n = 2 << k;
for(i = 0; i < n; i++)
{
while(k >= 0 || a[k] == 0)
k = k - 1;
if(a[k] == 1 )
{
a[k] = 0;
for(j = k; j > m; j++)
a[j] = 0;
}
for(j = 0; j < m; j++)
{
if(a[j] == 1)
printf(" %d", b[j]);
}
printf("\n");
}
printf("{ }\n");
getch();
}
看看这个对不对?
#10
由于数据较小,只有10个 < 32,有个更巧妙的方法,
采用联合体
Union
{
int i;
bool flag[32];
}
i变化
flag[16]能够遍历所有的组合.
注意取前面的几位
效率会更高一些;
对于数据过大的,就要用其他方法了。
上面所提到的算法,都没有注意采用增量式的寻找方法
在数据量很大的时候,内存是个问题:)
采用联合体
Union
{
int i;
bool flag[32];
}
i变化
flag[16]能够遍历所有的组合.
注意取前面的几位
效率会更高一些;
对于数据过大的,就要用其他方法了。
上面所提到的算法,都没有注意采用增量式的寻找方法
在数据量很大的时候,内存是个问题:)
#1
#include <stdio.h>
#define MAX 20
int results[MAX];
int step;
int numcomb;
void output()
{
int i;
for (i = 0; i < numcomb; i++)
{
printf("%3d", results[i]);
}
printf("\n");
}
void work(int lowerlimit, int upperlimit, int num)
{
int i;
for (i = lowerlimit; i <= upperlimit - num; i++)
{
results[step++] = i;
if (num > 1)
work(i + 1, upperlimit, num - 1);
if (step >= numcomb)
{
output();
}
step--;
}
}
void comb(int n, int m)
{
step = 0;
numcomb = m;
work(0, n, numcomb);
}
void subset(int n)
{
int i;
for (i = 1; i <= n; i++)
{
comb(n, i);
}
}
int main(void)
{
int n;
printf("Please input a integer between 1 and %d: ", MAX);
scanf("%d", &n);
if (n <= 0 || n > MAX)
{
printf("Input error.\n");
return 1;
}
subset(n);
return 0;
}
#2
所有子集。。。。。
输出MAX_N=5的情况:
0
1
2
3
4
0 1
0 2
0 3
0 4
1 2
1 3
1 4
2 3
2 4
3 4
0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
0 1 2 3
0 1 2 4
0 1 3 4
0 2 3 4
1 2 3 4
0 1 2 3 4
total group = 31
#include <stdio.h>
#define MAX_N 5
int g_arr[MAX_N] = {0};
__int64 g_cnt = 0;
void Recur(int* arr, int arr_size, int req_cnt)
{
if (req_cnt > 0)
{
//数据没有选够,从剩下的数据中继续选
//先选中最小的
arr[0] = 1;
//然后从剩下的arr_size - 1个数据中选req_cnt-1个数据
Recur(arr+1, arr_size - 1, req_cnt-1);
//回溯一下,跳过刚才选的那个最小数的情况
arr[0] = 0;
if ((arr_size - 1) >= (req_cnt ))
{
Recur(arr+1, arr_size - 1, req_cnt);
}
}
else
{
//找到一组完整数据
++g_cnt;
//输出组合
for(int i=0; i<MAX_N; i++)
{
if (g_arr[i] == 1)
{
printf("%d\t", i);
}
}
printf("\n");
}
}
int main(int argc, char* argv[])
{
for(int i=1; i<=MAX_N; i++)
Recur(g_arr, MAX_N, i);
printf("total group = %I64u\n", g_cnt);
return 0;
}
输出MAX_N=5的情况:
0
1
2
3
4
0 1
0 2
0 3
0 4
1 2
1 3
1 4
2 3
2 4
3 4
0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
0 1 2 3
0 1 2 4
0 1 3 4
0 2 3 4
1 2 3 4
0 1 2 3 4
total group = 31
#3
我还是先想到递归,因为这个问题等价于输出一个n层二叉树的所有叶子节点。
#4
#include <stdio.h>
#include <string.h>
#include <windows.h>
int a[16]={0};
unsigned long c[16]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
int b[16]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int huanerjinzhi(long d)
{
int i=0;
int count=1;int k=d;
int *p;p=a;
unsigned long *q;q=c;
memset(a,0,sizeof(int)*16);
if(!k) {return 0;}
else {while(k&=(k-1)){count++;}}
while(d)
{
if(d&(*q)){*p=1;d&=~(*q);p++;q++;}
else{*p=0;p++;q++;}
}
return count;
}
void jisuan(long n)
{
long i, j, t;
long r;
long k=(1<<n);
for(i=0;i<k;i++)
{
t=huanerjinzhi(i);
printf("{");
for(r=1,j=0;r<=t;j++)
if(a[j]==1){
if(r!=t)printf("%d,",b[j]);
else printf("%d",b[j]);r++;}
printf("}\n");
}
}
void main()
{
int n;
printf("input a number:\n");
scanf("%d", &n);
long lBegin = GetTickCount();
jisuan(n);
long lEnd = GetTickCount();
printf("%d\n",lEnd-lBegin);
}
#5
输出结果 n=5时
input a number:
5
{}
{1}
{2}
{1,2}
{3}
{1,3}
{2,3}
{1,2,3}
{4}
{1,4}
{2,4}
{1,2,4}
{3,4}
{1,3,4}
{2,3,4}
{1,2,3,4}
{5}
{1,5}
{2,5}
{1,2,5}
{3,5}
{1,3,5}
{2,3,5}
{1,2,3,5}
{4,5}
{1,4,5}
{2,4,5}
{1,2,4,5}
{3,4,5}
{1,3,4,5}
{2,3,4,5}
{1,2,3,4,5}
16
Press any key to continue
#6
//顺序反的...
#include <stdio.h>
#include <stdlib.h>
int zuoyi(int n)
{
int i = 1<<n;
return i-1;
}
int main()
{
int k[100];
int p = 0, q,i,j;
int n;
scanf("%d",&n);
p = zuoyi(n);
for ( i = 0; i <= p; i++ )
{
j = i;
for ( q = 0; j > 0; q++ )
{
k[q] = j%2;
j = j/2;
}
printf(" { ");
while (q--)
{
if ( k[q] ) printf("%d ",q+1);
}
printf("}\n");
}
return 0;
}
#7
谢谢你们,真的好强啊,不知道我什么时候才能达到你们的水平!
好像有一点问题,比如我测试二楼朋友的程序,令MAX_N=10,结果total group是1023没错,可是集合不全啊,是我的显示有问题吗?还是别的原因,如第一项为{023789}而没有小于它的项了
好像有一点问题,比如我测试二楼朋友的程序,令MAX_N=10,结果total group是1023没错,可是集合不全啊,是我的显示有问题吗?还是别的原因,如第一项为{023789}而没有小于它的项了
#8
RE: 7楼
输出数量超出了可显示的上限。
把它重定向到文件中看
比如:
myprog.exe > out.txt
输出数量超出了可显示的上限。
把它重定向到文件中看
比如:
myprog.exe > out.txt
#9
#define Max 20
main()
{
int a[Max] = {0}, b[Max] = {0};
int i, j, m, n, k;
scanf( "%d", &k);
for(i = 1; i < k, i++)
scanf("%d", b[Max]);
m = k;
n = 2 << k;
for(i = 0; i < n; i++)
{
while(k >= 0 || a[k] == 0)
k = k - 1;
if(a[k] == 1 )
{
a[k] = 0;
for(j = k; j > m; j++)
a[j] = 0;
}
for(j = 0; j < m; j++)
{
if(a[j] == 1)
printf(" %d", b[j]);
}
printf("\n");
}
printf("{ }\n");
getch();
}
看看这个对不对?
main()
{
int a[Max] = {0}, b[Max] = {0};
int i, j, m, n, k;
scanf( "%d", &k);
for(i = 1; i < k, i++)
scanf("%d", b[Max]);
m = k;
n = 2 << k;
for(i = 0; i < n; i++)
{
while(k >= 0 || a[k] == 0)
k = k - 1;
if(a[k] == 1 )
{
a[k] = 0;
for(j = k; j > m; j++)
a[j] = 0;
}
for(j = 0; j < m; j++)
{
if(a[j] == 1)
printf(" %d", b[j]);
}
printf("\n");
}
printf("{ }\n");
getch();
}
看看这个对不对?
#10
由于数据较小,只有10个 < 32,有个更巧妙的方法,
采用联合体
Union
{
int i;
bool flag[32];
}
i变化
flag[16]能够遍历所有的组合.
注意取前面的几位
效率会更高一些;
对于数据过大的,就要用其他方法了。
上面所提到的算法,都没有注意采用增量式的寻找方法
在数据量很大的时候,内存是个问题:)
采用联合体
Union
{
int i;
bool flag[32];
}
i变化
flag[16]能够遍历所有的组合.
注意取前面的几位
效率会更高一些;
对于数据过大的,就要用其他方法了。
上面所提到的算法,都没有注意采用增量式的寻找方法
在数据量很大的时候,内存是个问题:)