• 利用递归生成组合数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
    ",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("
    ");
    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("
    ");
    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
  • 相关阅读:
    [功能发布]Excel与PowerBI互通互联升级版连接SSAS和AzureAS
    个人永久性免费-Excel催化剂功能第115波-word、pdf、Excel、ppt、html等文件互转
    个人永久性免费-Excel催化剂功能第113波-将帮助文档的主动权归还用户手中
    个人永久性免费-Excel催化剂功能第106波-重新定义使用Excel功能方式
    [功能发布]Excel催化剂2周年巨献-网页数据采集功能发布,满足90%合理场景使用
    Rabbitmq(一)
    Redis(三)
    MVC action过滤器验证登录
    分布式缓存 Redis(二)
    分布式缓存 Redis(一)
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/3572177.html
Copyright © 2020-2023  润新知