递归
递归是什么?
程序调用自身就叫做递归,怎么理解?套娃!
https://www.bilibili.com/video/BV13K4y1j7Za
参考这个B站视频
为什么要用递归?
用递归去解决多重循环,杀人于无形
而递归跟循环的区别,循环注重过程,而递归值注重结果
怎么用递归?
分为三步
1.知道递归用来做什么
2.知道递归的结束条件
3.知道递归之间的关系
例题
汉诺塔
#include<bits/stdc++.h>
using namespace std;
int N;
void hanoi(int n,char crt,char mid,char dest)// 干啥,也就是为了把n个块从crt移到dest借助mid
{
if(n==1)//结束条件,到此就开始回溯
{
cout<<crt<<"->"<<dest<<endl;
return ;
}
hanoi(n-1,crt,dest,mid);// 把n-1个从crt借助dest移到mid
cout<<crt<<"->"<<dest<<endl;
hanoi(n-1,mid,crt,dest);//把n-1个从mid借助crt移到dest ,下面两步均为递归的关系,即为了满足a->c先要a->b然后b->c
}
int main()
{
cin>>N;
hanoi(N,'a','b','c');
return 0;
}
N皇后
要求n个国际象棋的皇后摆在n*n的棋盘上
且相互不能攻击,输出全部方案
输出结果里每一行都代表一种摆法
行里第i个数字代表第i行皇后放在第几列
输入:
4
输出:
2 4 1 3
3 1 4 2
#include<bits/stdc++.h>
using namespace std;
int N;
int queenpos[100];//皇后的位置
void Nqueen(int k)// 目的,从第k个开始摆,并摆在不冲突的位置
{
if(k==N)//结束条件,从此回溯
{
for(int i=0;i<N;i++)
cout<<queenpos[i]+1<<' ';//因为在数组从0开始,所以+1;
cout<<endl;
return ;
}
for(int i=0;i<N;i++)//以下为判断每个的摆放位置,并与下一个产生关联
{
int j;
for(j=0;j<k;j++)
{
if(queenpos[j]==i||abs(queenpos[j]-i)==abs(k-j)) break;//检查第k个放的如果是i位置是不是与前面的有冲突
}
if(j==k)
{
queenpos[j]=i;
Nqueen(k+1);
}
}
}
int main()
{
cin>>N;
Nqueen(0);//从0开始排,那些从1开始的边界一般是k>n
return 0;
}
上台阶
每次走1/2级台阶
n级台阶走法=
1.先走一级后,n-1级台阶走法
2.先走两级后,n-2级台阶走法f(n)=f(n-1)+f(n-2) n=1(其实这玩意不就是斐波那契吗)
#include<bits/stdc++.h>
using namespace std;
int stairs(int n)// 为了找n个台阶用多少种走法
{
if(n<0) return 0;//和下面一样都是终点
if(n==0) return 1;//这样的话就没必要特意声明1和2的条件了
return stairs(n-1)+stairs(n-2);//关联
}
int main()
{
int m;
while(cin>>m)
{
cout<<stairs(m)<<endl;
}
return 0;
}
P1287 盒子与球
题目描述
现有 rr 个互不相同的盒子和 nn 个互不相同的球,要将这 nn 个球放入 rr 个盒子中,且不允许有空盒子。请求出有多少种不同的放法。
两种放法不同当且仅当存在一个球使得该球在两种放法中放入了不同的盒子。
输入格式
输入只有一行两个整数,分别代表 nn 和 rr。
输出格式
输出一行一个整数代表答案。
输入输出样例
输入 #1复制
3 2
输出 #1复制
6
说明/提示
样例输入输出 1 解释
有两个盒子(编号为 1, 21,2)和三个球(编号为 1, 2, 31,2,3),共有六种方案,分别如下:
盒子编号 | 方案 1 | 方案 2 | 方案 3 | 方案 4 | 方案 5 | 方案 6 |
---|---|---|---|---|---|---|
盒子 11 | 小球 11 | 小球 22 | 小球 33 | 小球 2, 32,3 | 小球 1, 31,3 | 小球 1, 21,2 |
盒子 22 | 小球 2, 32,3 | 小球 1, 31,3 | 小球 1, 21,2 | 小球 11 | 小球 22 | 小球 33 |
数据规模与约定
对于 100\%100% 的数据,保证 0 \leq r \leq n \leq 100≤r≤n≤10,且答案小于 2^{31}231。
百度链接 斯特灵数:https://baike.baidu.com/item/%E6%96%AF%E7%89%B9%E6%9E%97%E6%95%B0/4938529?fr=aladdin
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll f(int n,int m)
{
if (m <= 0 || n < m)//(2)递归结束条件
return 0;
if (n == m)//(2)递归结束条件
return 1;
else
return f(n-1, m-1) + f(n-1, m) * m;/*(1)用来干什么(3)递归之间的关系
用来模拟放小球,
1.第n个小球单独占一个盒子其余n-1个放其
他m-1个盒子里
2.和其他的放一起,先把n-1个安排好,第n个
可以放在其他m个盒子中的一个*/
}
ll fc(int i)
{
if(i==1) return 1;
else return i*fc(i-1);
}
int main()
{
ll n,m;
cin>>n>>m;
cout<<f(n,m)*fc(m)<<endl;
return 0;
}
看这又一篇漫画就是将爬楼梯https://zhuanlan.zhihu.com/p/31628866
他说这就叫动态规划,我后面的内容才是动态规划欸,那我不是超纲了,不不不,后面你会开心的发现,什么动态规划,什么dfs,bfs都是套娃而已。
郭炜老师mooc链接:https://www.icourse163.org/learn/PKU-1001894005?tid=1461679488