二.递归函数总结

递归函数

递归就是把大问题依次分解,分解到可以明显可见的小问题,加上终止条件,找出大问题与小问题的关系,还是要多思考才能得到这种关系。

递归函数包含递归边界及递归关系式,而找出递归关系式是重难点。有些递归可以演变为记忆化搜索,减少重复运算。但还是要多多体会递归的意义以及其方法,找出问题的本质,当然这需要多做题,多反思才行。从大问题不好入手,从小问题先来看,逐层思考,以小看大,又可能想出问题解决办法。

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;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值