递归思想分析解决问题

1 篇文章 0 订阅
1 篇文章 0 订阅

递归(英语:recursion,re(repeat,return)+cur(occur 发生),是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法。例如,斐波纳契数列 0,1,1,2,3,5,8,13,21,34,55,89,144...的定义:f0=0,f1=1,fn=f(n-1)+f(n-2)(n>=2,n为正整数)这个定义过程其实是自己定义自己。

它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的已解决或容易解决的问题来求解。“抢30游戏”中,从1开始,两人轮流报数,要求每次只能报1个或2个数,先报出30的人赢。咋一看,这个问题有点复杂,但也引人进一步地分析,先报出27就赢了→先报出24赢 →21 →18 →15 →12 →9→6 →3 ,先报出3的人赢,这就一目了然了。

那么如何运用递归方法来解决问题呢? 一个问题能否适用递归方法解决,必须要符合两个条件:①有明确的结束条件,或称递归边界条件,它直接确定问题的最简单情况;②一个规模较大的问题可以向下分解为若干个性质相同的规模较小的问题,并最终归结为递归边界条件。

具体到实际,汉诺塔问题和购票问题又如何分析解决呢?

汉诺塔:

 

将n个盘子从一个柱子移到另一个柱子,首先将第n个盘子上的n-1个盘子看做一个整体,考虑n-1个盘子的移动问题,再如此一步步缩小问题规模,直到整个问题最终归结为n=1的情形。

 

设f(n)为将n个盘子从一个柱子移到另一个柱子所需最少步数,则整个问题的解决所需最少步数为f(n)=2f(n-1)+1 (n>=2),当n=1时,f(1)=1.即:

 

                    

 

n-1个盘子的整体,它的移动再调用上面的函数,这样不断的缩小规模,递归调用,完成全部盘子的移动。

由此容易得出它的递归程序:

public class Hanoi

{

public static double f(double n)

{

if(n==1)

return 1;

else

return 2*f(n-1)+1;

}

public static void main(String args[])

{

System.out.println(f(3));

}

}

 

以上java程序的执行结果:

 

 

 

 

购票:

盛况空前的足球赛即将举行。球赛门票售票处排起了球迷购票长龙。按售票处规定,每位购票者限购一张门票,且每张票售价为50元。在排成长龙的球迷中有m个人手持面值50元的钱币,另有n个人手持面值100元的钱币。假设售票处在开始售票时没有零钱。试问这m+n个球迷有多少种排队方式可使售票处不致出现找不出钱的尴尬局面。 
例如当m=3,n=2时,用A表示手持面值50元钱币的球迷,用B表示手持面值100元钱币的球迷,则最多可得到以下5组不同排队方式,使售票处不致出现找不出钱的尴尬局面。 

售票处 A A A B B 
售票处 A A B A B 
售票处 A B A A B 
售票处 A A B B A 
售票处 A B A B A 

 

规模大的购票过程总是由规模小的购票过程组成,因此该问题是一个自相拟的问题,可用递归方法解决。

令f(m,n)表示m个人手持50元钞票、n个人手持100元钞票时的排队方式总数。显然,只有售票处收到的零钱总数不少于找出的零钱总数,购票才有可能成功。即当m<n时,f(m,n)=0,下面考虑m>=n的情形。

采用递归法,m+n个人购票可以视为分两步完成:前面m+n-1个人购票;最后一个人购票。注意到,此时若前面m+n-1个人购票成功,则最后一个人也一定能购票成功,因为m>=n,如果最后一个人需要找零的话,前面排队的人的组成是m和n-1,m>n-1,是有零钱可找的。前面m+n-1个人的组成由两种情况:m-1和nm和n-1。这两种情况的排队方式不一样,所以有f(m,n)=f(m-1,n)+f(m,n-1)

这样分成两步,问题规模变小了。把f(m,n)的问题转化为f(m-1,n)的问题和f(m,n-1)的问题,也就是规模上要么第一元少1,要么第二元少1。问题最终总会归结为两种情形:一是第一元小于第二元,二是第二元变为零。第一元小于第二元时,f(m,n)=0,下面考虑第二种情形。

当n=0时,所有人手中拿的都是50元的钞票,无需找零,购票总能成功,由于只考虑50元与100元钞票间隔的方式,所以此时f(m,n)=1。综上所述,f(m,n)的递归计算公式为:

           

由此容易得出它的递归程序:

public class Buy

{

   public static double f(double m,double n)

   {

        if(n==0) return 1;

        else if (m<n)

           { return 0; 

           }

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

   }

   public static void main(String args[])

   {

     System.out.println(f(3,2));

   }

}

 

以上java程序的执行结果:

 

 

 

 

 

 参考资料:

 递归趣闻【matrix67】 CSDN博客

 递归方法与问题解决 北京东城区中学信息技术教研网

《数学思想方法通论》 熊惠民 科学出版社

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值