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~