快乐写递归

hello吖~ 之前一直不太理解递归程序是怎么走下去的,以至于dfs一直理解不了,这两天比较深入的学习了一下,才恍然大悟哈哈哈,今天又去听mooc翁恺老师的课才瞬间明白,然后就突然懂了搜索的奥妙哈哈,是解决了困扰已久的迷。递归是很基础啦,经典递归大概就是有,求阶乘,斐波那契数列,汉诺塔,等很多题 ,今天就总结一下这几天写递归的题目,加深自己的理解。写完之后其实不难发现,用递归就是把一个大问题逐层拆分成子问题来解决哒,精髓所在hhh~

在这里插入图片描述

经典汉诺塔
从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数。
思路:之前也是很很不理解汉诺塔,现在此小白来写写解析供食用 ,首先要将n个盘子借助b从a移动到c上,它的上一步操作是要先把n-1个盘子借助c从a移动到b上 ,再上一步就是借助b将n-2个盘子从a移到c上,以此类推就会理解辽~
例如三个盘子的话,将三个盘子从a移动到c,上一步将两个盘子从a移动到b,再上一步将一个盘子从a移动到c,此时程序完成递归,over。

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std ;

void hanoi(int n ,char a , char c , char b)//借助c将n个盘子从a移动到b
{
    if(n==1)
    {
        cout << a << "->" << b << endl ;
        return ;
    }
    hanoi(n-1 , a , b , c) ;
    cout << a << "->" << b << endl ;
    hanoi(n-1 , c , a , b) ;
    return ;
}
int main()
{
    int n ;
    cin >> n ;
    hanoi(n , 'A' , 'B' , 'C') ;
    return 0 ;
}

N皇后问题
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

思路:理解汉诺塔之后这个题也就不难搞懂了,要求每个皇后不在同一行同一列同一对角线,要枚举每一行的情况,当前这种情况和前面几行摆放不冲突的话就继续往下一行走下去,到哪个地方不满足了就跳出,枚举下一种情况,具体代码如下~

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std ;
//N皇后问题(递归)

int N ;
int queen[110] ;

void Queen(int n) //摆放第n-1行的皇后
{
    if(n==N)
    {
        for(int i = 0 ; i < N ; i ++)
            cout << queen[i]+1 << ' ' ;
        cout << endl ;
        return ;
    }
    for(int i = 0 ; i < N ; i ++) //枚举每一行的每个位置
    {
        int j  = 0 ;
        for(j = 0 ; j < n ; j ++) //判断前n-1个皇后的位置是否与第n个皇后的位置有冲突
            if(queen[j] == i || abs(queen[j]-i)==abs(n-j)) 
            //每个皇后不在同一列,且不同一对角线。
                break ;
        if(j==n) //第n行的皇后放在第i个位置满足条件的话,程序走到下一行,
            queen[n] = i , Queen(n+1) ;
    }
}

int main()
{
    cin >> N ;
    Queen(0) ;//从第0行开始
    return 0 ;
}

爬楼梯
题目:N阶楼梯,一次走一级或者两级,求不同走法数。
思路:emmmm,其实跟汉诺塔思路差不多,因为最后一次走可以是走一阶或者两阶,所以走n阶台阶的走法,就等于退一阶后,前面n-1阶台阶的走法 ,加上退两阶台阶,前面n-2阶台阶的走法,表达式即为:f(n)=f(n-1)+f(n-2) ,然后再判断一下边界条件n为0或者n为1的条件就ok啦~

#include <iostream>
#include <algorithm>

using namespace std ;

int stair(int n)
{
    if(n < 0)
        return 0 ;
    if(n==0)
        return 1 ;
    else
        return stair(n-1)+stair(n-2) ;
}

int main()
{
    int n ;
    while(cin >> n && n)
        cout << stair(n) << endl ;
    return 0 ;
}

写完这个想到了今天写的另一个题目,它的数据量比这个要大的多,它用递归就不行了,所以就要用令人头痛的dp了,emmm,还是以后写叭在这里插入图片描述
放苹果
题目:把M个同样的苹果放在N个同样的盘子里,允许盘子为空,求有几种放法。
思路:先来假设苹果比盘子多的情况,m个苹果放在n个盘子,首先没有空盘子的话,就是每个盘子都先放一个苹果,此时苹果数量变为m-n,然后就是将m-n个苹果放入n个盘子,依次递归再次实现以上操作,当苹果数量减为1时,此时盘子不放放法就是只有一种;其次是有盘子为空的情况,一个盘子为空数量变为n-1,递归以上操作,然后-2 ,-3 ,emmm ,依次递归下去,实现求解,当盘子数量为0时,放法数量也就为0 ;当苹果没有盘子多的时候呢,就相当于必有n-m个盘子为空,就直接等于m个苹果放在前m个盘子的情况了,in short , 综上所述,f(m , n)=f(m , n-1)+f(m-n,n) 。

#include <iostream>
#include <algorithm>

using namespace std ;

int apple(int m , int n)
{
    if(n > m)
        return  apple(m , m);
    if(m==0)
        return 1 ;
    if(n==0)
        return 0 ;
    else
        return apple(m , n-1)+apple(m-n , n) ;
}

int main()
{
    int m , n ;
    cin >> m >> n ;
    cout << apple(m , n) << endl ;
    return 0 ;
}

in the end ,
首先将一个问题逐层拆分成一个个子问题,之后根据每种情况推出递推式,最后不要忘记边界情况,组合一下就ok啦~ ,细心做题冲冲冲!!!

快快乐乐写代码,byebye~
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值