/*===================================== 數的組合問題。從1,2,…,n中取出m個數,將所有組合按照字典順序列出。 如n=3,m=2時,輸出: 1 2 1 3 2 3 這里只考慮從互不相同的n個數當中選擇m個的情況。 我的思路:
這里采用的思路和上回解決遞歸生成全排列的思路差不多。
從a數組的n個數當中選m個到ans數組。
每一次選擇一個數到ans[i]時都在a數組中掃描並依次選擇所有的可能。
但是這里掃描的范圍是從ans[i-1]在a中的下標k的下一個開始,一直掃描到n-(m-i-1)的前一個位置為止。
這個范圍是ans[i]的可能選擇的范圍。(后面還要選一部分才湊夠m個數,故不能掃描到a數組的末尾。)
======================================*/

1 #include<stdio.h> 2 int count=0; 3 void fun(int a[],int n,int m,int i,int k,int ans[]); 4 //原始數組a[],從a數組的n個數當中選m個數,結果放在ans數組。 5 //i表示當前要選取第i個數。i從0開始。k表示上一次選取的數在a數組當中的下標。 6 //最開始時k==-1,表示還沒選數據。 7 int main() 8 { 9 int n,m,a[30],ans[30],i; 10 freopen("5.out","w",stdout); 11 scanf("%d%d",&n,&m); 12 for(i=0;i<n;i++) 13 { 14 //scanf("%d",&a[i]); 15 a[i]=i+1; 16 } 17 fun(a,n,m,0,-1,ans); 18 printf("%d\n",count); 19 return 0; 20 } 21 void fun(int a[],int n,int m,int i,int k,int ans[]) 22 //原始數組a[],從a數組的n個數當中選m個數,結果放在ans數組。 23 //i表示當前要選取第i個數。i從0開始計數。k表示上一次選取的數在a數組當中的下標。 24 //最開始時k==-1,表示還沒選數據。 25 { 26 int j; 27 if(i==m) 28 { 29 for(j=0;j<m;j++) printf("%d ",ans[j]); 30 printf("\n"); 31 count++; 32 return ; 33 } 34 else 35 { 36 for(j=k+1;j<n-(m-i-1);j++)//從第k+1個開始,嘗試選擇第i個數。(注意:i從0開始計算) 37 { 38 ans[i]=a[j]; 39 fun(a,n,m,i+1,j,ans); 40 } 41 } 42 }
下面是網上的做法,思路挺好的。
來源:http://blog.csdn.net/challenge_c_plusplus/article/details/6641950
原文如下:
此法借鑒了2009年華為一筆試題我寫的一個遞歸算法
http://blog.csdn.net/challenge_c_plusplus/article/details/6640530
排列數的遞歸實現見我的另一篇
http://blog.csdn.net/challenge_c_plusplus/article/details/6574788

1 /* 2 * 功能:輸出組合數C(n,m) 3 * 日期:2011/7/28 4 * 作者:milo 5 * 不足:對於有多個重復數字,會輸出重復的組合數,可以通過遍歷一個數組鏈表解決。 6 */ 7 8 #include<stdio.h> 9 #include<stdlib.h> 10 11 int *dst_array,top=0,count=0;//中間數組,存放中間求解過程,count計數所有的組合個數 12 13 //打印長度為n的數組元素 14 static void printA(int *parray,int n) 15 { 16 int i; 17 for(i=0;i<n;i++){ 18 printf("%d ",parray[i]); 19 } 20 } 21 22 //遞歸打印組合數 23 static void print_combine(int *pArray,int n,int m) 24 { 25 if(n < m || m==0) return ;//情況一:不符合條件,返回 26 print_combine(pArray+1,n-1,m);//情況二:不包含當前元素的所有的組合 27 dst_array[top++]=pArray[0];//情況三:包含當前元素 28 if(m==1){//情況三-1:截止到當前元素 29 printA(dst_array,top); 30 printf("\n"); 31 count++; 32 top--; 33 return; 34 } 35 print_combine(pArray+1,n-1,m-1);//情況三-2:包含當前元素但尚未截止 36 top--;//返回前恢復top值 37 } 38 39 int main() 40 { 41 int n,m,*parray;//存放數據的數組,及n和m 42 scanf("%d%d",&n,&m); 43 parray=(int *)malloc(sizeof(int)*n); 44 dst_array=(int *)malloc(sizeof(int)*m); 45 int i; 46 for(i=0;i<n;i++){//初始化數組 47 scanf("%d",&parray[i]); 48 } 49 print_combine(parray,n,m);//求數組中所有數的組合 50 printf("=====C(%d,%d)共計:%d個=====",n,m,count); 51 return 0; 52 }