- void comb_back(int a[],int m,int r)
- {
- int i,j,k=0;
- i=0,a[i]=1;
- do
- {
- if (a[i]-i<=m-r+1)
- {
- // 相等就找到组合
- if (i==r-1)
- {
- printf( "第%d组: ",++k);
- for(j=0;j <r;j++)
- printf( "%d ",a[j]);printf( "/n ");
- // 最后的一个元素加1
- a[i]++;
- continue;
- }
- i++; //向前试探
- a[i]=a[i-1]+1;
- }
- else
- {
- //回溯
- if(i==0)
- return;//已找到了全部解
- a[--i]++;
- }
- }while(1);
- }
- // Function:从n个数中选择m个数进行组合的非递归算法。
- /*
- 首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。
- 然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为
- “01”组合,同时将其左边的所有“1”全部移动到数组的最左端。
- 当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得
- 到了最后一个组合。
- 例如求5中选3的组合:
- 1 1 1 0 0 //1,2,3
- 1 1 0 1 0 //1,2,4
- 1 0 1 1 0 //1,3,4
- 0 1 1 1 0 //2,3,4
- 1 1 0 0 1 //1,2,5
- 1 0 1 0 1 //1,3,5
- 0 1 1 0 1 //2,3,5
- 1 0 0 1 1 //1,4,5
- 0 1 0 1 1 //2,4,5
- 0 0 1 1 1 //3,4,5
- */
- #include "stdafx.h"
- #include <stdio.h>
- #include <stdlib.h>
- void C(int N, int M, int *Num)
- {
- int i;
- bool ifok = false;
- // 10前面连续0的个数
- int iZero = 0;
- // 10前面连续1的个数
- int iOne = 0;
- // 初始化第一个组合
- for (i=0; i<M; i++)
- {
- Num[i] = 1;
- printf("%d", i+1);
- }
- printf("/n");
- // N-M个数为0
- for (i=M; i<N; i++)
- Num[i] = 0;
- if (M == N)
- ifok = true;
- while(!ifok)
- {
- iOne = 0;
- iZero = 0;
- // 从第一个数开始找10
- for (i=0; i<N; i++)
- {
- // 找到10
- if ( 1 == Num[i] && 0 == Num[i+1])
- {
- Num[i] = 0;
- Num[i+1] = 1;
- break;
- }
- // 找到1且下一个不是0
- else if (1 == Num[i] && 0 != Num[i+1])
- {
- iOne++;
- }
- // 计算连续0的个数
- else if (0 == Num[i])
- {
- iZero++;
- }
- }
- if (iZero)
- {
- // 把左边的所有1移到左端
- for (i=0; i<iOne; i++)
- {
- Num[i] = 1;
- }
- for (i=iOne; i<iOne+iZero; i++)
- {
- Num[i] = 0;
- }
- }
- // 输出结果
- for (i=0; i<N; i++)
- {
- if (Num[i] == 1)
- printf("%d", i+1);
- }
- // 换行
- printf("/n");
- // 判断是否输出了所有的组合
- for (i=N-M; i<N; i++)
- {
- if (0 == Num[i])
- break;
- }
- if (Num[N-1] != 0 && i == N)
- ifok = true;
- }
- }
- int main(void)
- {
- int N;
- int M;
- scanf("%d%d", &N, &M);
- int *Num = (int *)malloc(sizeof(int)*N);
- C( N, M,Num);
- free(Num);
- return 0;
- }
- // 递归算法
- /// 求从数组a[1..n]中任选m个元素的所有组合。
- /// a[1..n]表示候选集,n为候选集大小,n>=m>0。
- /// b[1..M]用来存储当前组合中的元素(这里存储的是元素下标),
- /// 常量M表示满足条件的一个组合中元素的个数,M=m,这两个参数仅用来输出结果。
- void combine( int a[], int n, int m, int b[], const int M )
- {
- for(int i=n; i>=m; i--) // 注意这里的循环范围
- {
- b[m-1] = i - 1;
- if (m > 1)
- combine(a,i-1,m-1,b,M);
- else // m == 1, 输出一个组合
- {
- for(int j=0; j<M; j++)
- printf("%d", a[b[j]]);
- printf("/n");
- }
- }