递归函数
递归就是把大问题依次分解,分解到可以明显可见的小问题,加上终止条件,找出大问题与小问题的关系,还是要多思考才能得到这种关系。
递归函数包含递归边界及递归关系式,而找出递归关系式是重难点。有些递归可以演变为记忆化搜索,减少重复运算。但还是要多多体会递归的意义以及其方法,找出问题的本质,当然这需要多做题,多反思才行。从大问题不好入手,从小问题先来看,逐层思考,以小看大,又可能想出问题解决办法。
1.例如求n!
#include<bits/stdc++.h>
using namespace std;
int n;
int fact(int n)
{
if(n==1)return 1;//递归边界
else return fact(n-1)*n;//转化成求n*(n-1)!问题,当n为1时其阶乘显而易见
}
int main()
{
cin>>n;
cout<<fact(n);
return 0;
}
2.特殊数列Fibonacci数//递归函数变为记忆化搜索
代码如下
#include<bits/stdc++.h>
using namespace std;
int f[1000],n;
int main()
{
f[0]=1;
f[1]=1;//边界
cin>>n;
for(int i=2;i<=n;i++)
{
f[i]=f[i-1]+f[i-2];//递归关系式
}
cout<<f[n]<<endl;
}
3.//有些递归类似深度优先搜索
全排列问题代码
#include<bits/stdc++.h>
using namespace std;
int h;
void perm(int list[],int k,int m)
{
int i,j;
if(k==m)
{
for(i=h;i<=m;i++)
cout<<list[i]<<" ";
cout<<endl;
}
else
for(j=k;j<=m;j++)
{
swap(list[k],list[j]);
perm(list,k+1,m);//深度优先搜索//递归,固定一个位置,讨论下一个,挨个讨论
swap(list[k],list[j]);//回溯
}
}
int main()
{
int list[]={1,2,3,4,5,6,7},k,m,i,j;
h=2;
perm(list,2,4);
}
4.
//半数集问题//其子问题解法之和加起来是其问题的解,找出递归关系;用记忆化搜索方式可以提高代码运行效率
#include<bits/stdc++.h>
using namespace std;
int a[10000],n,i;
int com(int n)
{
int ans=1;
if(a[n]>0)return a[n];
for(i=1;i<=n/2;i++)
ans+=com(i);//递归过程,把i传给n,依次递归
a[n]=ans;
return ans;
}
int main()
{
cin>>n;
cout<<com(n);
return 0;
}
5.递归
一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n * n的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不能通行。同时当Extense处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,Extense想要从点A走到点B,问在不走出迷宫的情况下能不能办到。如果起点或者终点有一个不能通行(为#),则看成无法办到。
//深度优先搜索+递归openjudge
//但广度优先搜为什么不对啊
#include<cstdio>
#include<iostream>
using namespace std;
char a[101][101];
int t,n,x,y,
fx[5]={0,0,1,0,-1},
fy[5]={0,1,0,-1,0},
rx,ry,cx,cy;
bool sfzd,flag,vis[101][101];
void bfs(int i){
for(int j=1;j<=4;j++){
if(a[x+fx[j]][y+fy[j]]=='.'&&!vis[x+fx[j]][y+fy[j]]){
x+=fx[j];y+=fy[j];
vis[x][y]=1;
if(x==cx&&y==cy) {sfzd=true;flag=true;break;}
else bfs(i+1);
if(!flag) {x-=fx[j];y-=fy[j];vis[x][y]=0;}
else break;
}
}
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
vis[i][j]=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
cin>>rx>>ry>>cx>>cy;
x=rx;y=ry;
if(a[x][y]=='.')
bfs(1);
printf("%s\n",sfzd?"YES":"NO");
sfzd=false;flag=false;
}
return 0;
}