zoukankan      html  css  js  c++  java
  • 若干蓝桥杯递归题

    (1)放苹果:M个同样的苹果放N个同样的盘子,允许有盘子空着, 问有多少种放法。

      注意:5 1 1和1 5 1是同一种放法     

      分析:

        分两种情况:     

        a.至少有一个盘子为空。此时放法种数与减去这个空盘子的放法种数相同。     

        b.所有盘子都不为空。此时可以从每个盘子里拿掉一个苹果而不影响放法种数。    

        显然m<n时,只能满足第一种情况.

      很好的算法: f(m, n) = f(m-n, n) + f(m, n-1)

      f(m, n): 把m个苹果放到n个盘子中的方法数 f(m, n-1): 把m个苹果放到n-1个盘子中的方法数(其中至少有一个空盘子) f(m-n, n): 把m个苹果放到n个盘子中,而且每个盘子中都有苹果(先拿n个出来,等m-n个放好了,然后每个盘子放一个)

      

     1 int PlaceApple(int m, int  n)
     2 {
     3     if(m < 0)
     4         return 0;
     5     if(m  == 0)   //每个盘子一个
     6         return 1;
     7     if(n == 1)   //只有一个盘子
     8         return 1;
     9     return PlaceApple(m - n, n) + PlaceApple(m, n - 1);
    10 }

    (2)计算3个A,2个B可以组成多少种排列的问题(如:AAABB, AABBA)是《组合数学》的研究领域。但有些情况下,也可以利用计算机计算速度快的特点通过巧妙的推理来解决问题。下列的程序计算了m个A,n个B可以组合成多少个不同排列的问题。请完善它。

    int f(int m, int n) {     if(m==0 || n==0) return 1;     return f(m-1, n) + f(m, n-1); }    

    分析:首先明确这个函数的功能是:求m个A和n个B可以组成多少种排列。

      此时分两种情况:      a.排列的第一个元素是A。      b.排列的第一个元素是B。

    把这两种情况的排列种数加起来即可.

     (3)某布袋中有红球m个,白球n个,现在要从中取出x个求,红球数目多于白球的数目的概率是多少。下面的代码解决这个问题,其中y表示红球至少要出现的次数。
           分析:明确函数的定义:求m个红球、n个白球的布袋中取出x个球,红球数目大于白球的概率。注意到m/(m+n)表示取出的球是红球的概率,n/(m+n)表示取出的球是白球的概率。现在从布袋中取一个球出来

      有两种情况:
          a.取出的是红球
          b.取出的是白球.
      然后根据不同的情况判断m、n、x、y的变化。

     1 代码:
     2 //m个红球,n个白球,从中取出x个求,y表示红球至少要出现的次数
     3 double f( int m, int n, int x,int y)
     4 {
     5 if(y>x) return 0;
     6 if(y==0) return 1;
     7 if(y>m) return 0;
     8 if(x-n>y) return 1;
     9 /*
    10 m/(m+n)表示第一次选红球,随后的就重复了
    11 */
    12 double p1 = f(m-1,n,x-1,y-1);
    13 double p2 = f(m,n-1,x-1,y);
    14 return (double)m/(m+n)*p1+(double)n/(m+n)*p2;
    15 }

    4)假设有m+n个人,其中,m个人手持面额为5角的硬币,n个人手持面额为1元的硬币,他们都要乘车买票,现假设售票员手中无零钞,票价为5角,下面这个函数就可以算出这m+n个人所有可能的买票情况(顺利

    完成购票过程的购票次序的种类数),请完善此函数 int f(int m, int n) {         if(m < n) return 0;         if(n==0) return

    1;       return f(m-1 , n) + f( m , n-1) ;}

      一般的想法是从前往后发现规律,但这题确是从后考虑。

      分两种情况:

      (1)最后一个上车的,持有1元硬币。           前m+n-1个人有:f(m,n-1)

      (2)最后一个上车的,持有0.5元硬币。           前m+n-1个人有:f(m-1,n)

    (5)整数划分
      如,对于正整数n=6,可以分划为:
      6
      5+1
      4+2, 4+1+1
      3+3, 3+2+1, 3+1+1+1
      2+2+2, 2+2+1+1, 2+1+1+1+1
      1+1+1+1+1+1+1
      总共有十一种划分,求一个数总共有多少种这样的划分。

    根据n和m的关系,考虑以下几种情况:

           (1)当n=1时,不论m的值为多少(m>0),只有一种划分即{1};

            (2)  当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,...,1};

            (3)  当n=m时,根据划分中是否包含n,可以分为两种情况:

                  (a). 划分中包含n的情况,只有一个即{n};

                  (b). 划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。

                  因此 f(n,n) =1 + f(n,n-1);

            (4) 当n<m时,由于划分中不可能出现负数,因此就相当于f(n,n);

            (5) 但n>m时,根据划分中是否包含最大值m,可以分为两种情况:

                   (a). 划分中包含m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分

                         个数为f(n-m, m);

                   (b). 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1);

                  因此 f(n, m) = f(n-m, m)+f(n,m-1);

             综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中(1)和(2)属于回归条件,(3)和(4)属于特殊情况,将会转换为情况(5)。而情况(5)为通用情况,属于递推的方法,其本质主要是通过减小m以达到回归条件,从而解决问题。其递推表达式如下:

             f(n, m)=       1;                                (n=1 or m=1)

                                f(n, n);                         (n<m)

                                1+ f(n, m-1);                (n=m)

                                f(n-m,m)+f(n,m-1);       (n>m)

  • 相关阅读:
    Cstring 和 const char* , unicode和ANSI编码 的一个具体应用(转)
    引用 CTreeCtrl中用右键选中item并弹出菜单的方法(转)
    Android 开发人员必须掌握的 10 个开发工具
    关于在线程中使用AfxGetMainWnd()出错的问题,终于找到了
    MFC CListCtrl的用法.Style/插入、删除、选中数据及排序问题等(转)
    vc++ 中的匈牙利变量表示法
    Android模拟器安装程序及上传音乐并播放
    关于CString总结(转)
    MSSQL优化之————探索MSSQL执行计划(转)
    抓虫系列(三) 不要轻视web程序中常用的三个"池" 之数据库连接池
  • 原文地址:https://www.cnblogs.com/hxsyl/p/3044634.html
Copyright © 2011-2022 走看看