利用遞歸生成組合數C(n,m)


/*=====================================
數的組合問題。從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 }
View Code

 

 

下面是網上的做法,思路挺好的。

來源: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 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM