设为首页 加入收藏

TOP

2.6.3 从n个事物中选出k个
2014-03-11 13:06:25 来源: 作者: 【 】 浏览:186
Tags:2.6.3 事物 选出

2.6.3  从n个事物中选出k个

某支摇滚乐队希望在n个城市巡回演出。遗憾的是,由于时间原因只能访问k个城市。乐队经纪人考虑从n个可能的城市选择k个城市的不同选择。由于时间紧迫,乐队成员不考虑访问k个城市的顺序。

令g(n,k)为从n个城市选择k个城市的方案数目。考虑城市C,那么只有访问与不访问两种选择。如果访问城市C,那么就需要从n-1个剩余的城市中选择k-1个城市。因此,包含城市C的方案数目为g(n-1, k-1)。相反,如果不访问城市C,就必须从剩余的n-1个城市中选择k个城市。不包含C的方案数目为g(n-1, k)。因此,可以将g(n,k)分解为相同类型的两个较小的问题,也就是说:

g(n, k) = g(n-1, k-1) + g(n-1, k)

注释:从n个事物中选择k个的方案数目等于从n-1个事物中选择k-1个的方案数目加上从n-1个事物中选择k个的方案数目

我们仍然需要找到基例,并说明这两个较小的问题最终都能够到达基例。首先,如果乐队有时间到达全部n个城市,也就是说k等于n,那么方案只有一种。因此,第一个基例为:

g(k, k) = 1

如果k<n,则递归定义中的第二项g(n-1,k)可以到达这个基例,因为在连续的递归过程中,n-1持续下降到k。然而,第一项g(n-1, k-1)不会到达这个基例。由于n-1与k-1以同样的速率下降,因此永远不会相等。实际上,第一项是另一个旅程选择问题。就像访问所有城市只有一个选择(k=n)那样,访问0个城市也只有一个选择(k=0)。因此,第二个基例是:

g(n, 0)=1

第一项g(n-1, k-1)最终将到达这个基例(此外,也可以将第二个基例定义为g(n,1)=n)。

提示:当通过解决两个(或者多个)较小问题来解决某个问题时,每个较小问题必须比原始问题更靠近基例。

为了完整性,将最后一部分添加到递归解决方案中:

g(n, k) = 0    若k >n

尽管在本问题中,k不会大于n;但是这部分内容的加入可使该递归解决方案更加通用。

总而言之,下面的递归解决方案可以解决从n个事物中选择k个的问题:
 

注释:从n个事物中递归选择k个事物的方案数目

根据这个递归定义,不难得出下面的函数:
 

  1. /** Computes the number of groups of k out of n things.  
  2. @pre  n and k are nonnegative integers.  
  3. @post  None.  
  4. @param n  The given number of things.  
  5. @param k  The given number to choose.  
  6. @return  g(n, k). */  
  7. int getNumberOfGroups(int n, int k)  
  8. {  
  9. if ( (k == 0) || (k == n) )  
  10. return 1;  
  11. else if (k > n)  
  12. return  0;  
  13. else  
  14. return getNumberOfGroups(n - 1, k - 1) + getNumberOfGroups(n - 1, k);  
  15. } // end getNumberOfGroups 

与rabbit函数类似,该函数的效率不高且不实用。图2-20显示计算g(4, 2)时需要的递归调用数目。

提示:当递归函数包含多个递归调用时,通常需要多个基例。

问题10 计算g(4, 2)。
 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇12.3 数字图像的混沌加密简介 下一篇2.7 递归和效率

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·HTTPS 详解一:附带 (2025-12-26 02:20:37)
·TCP/IP协议到底在讲 (2025-12-26 02:20:34)
·TCP和UDP在socket编 (2025-12-26 02:20:32)
·有没有适合新手练习 (2025-12-26 01:48:47)
·用清华镜像网怎么下 (2025-12-26 01:48:44)