C++ 算法学习——1.6 递推递归

递推递归是分治思想的体现,核心都是将问题分为结构相似的子问题。递推侧重于多米诺结构,递归侧重于包含结构。

对于递推,关键在于自下而上的找到多米诺骨牌上下者联系,进而写出递推方程。

P1.以洛谷P1002过河卒为例

分析子问题,从终点开始,附近点作为起点的条数是易知的,这是“下者”,对应某个上者,它的条数就是对应下者(右或下)的条数相加,即p[i,j]=p[i+1,j]+p[i,j+1]

#include<iostream>
using namespace std;

bool inthemap(int n,int m,int ntest,int mtest)
{
    return ntest>=0&&ntest<=n&&mtest>=0&&mtest<=m;
}

struct mapspot
{
    long long nums;
    bool avail;
};

int main()
{
    int n,m,horsen,horsem;
    cin>>n>>m>>horsen>>horsem;
    mapspot** mapp=new mapspot*[n+1];
    for(int i=0;i<n+1;i++)
    {
        mapp[i]=new mapspot[m+1];
        for(int j=0;j<m+1;j++)
        {
            mapp[i][j].avail=1;
            mapp[i][j].nums=0;
        }
    }
    mapp[n][m].nums=1;

    int x[9]={-2,-2,-1,-1,0,1,1,2,2};
    int y[9]={-1,1,-2,2,0,2,-2,1,-1};
    for(int i=0;i<9;i++)
    if(inthemap(n,m,horsen+y[i],horsem+x[i]))  mapp[horsen+y[i]][horsem+x[i]].avail=0;

    for(int i=n;i>=0;i--)//从底层到上层,为递推
    {
        for(int j=m;j>=0;j--)
        {
            if(inthemap(n,m,i+1,j)&&inthemap(n,m,i,j+1)) if(mapp[i][j].avail==1) mapp[i][j].nums=mapp[i+1][j].nums+mapp[i][j+1].nums;
            if(!inthemap(n,m,i+1,j)&&inthemap(n,m,i,j+1)) if(mapp[i][j].avail==1) mapp[i][j].nums=mapp[i][j+1].nums;
            if(inthemap(n,m,i+1,j)&&!inthemap(n,m,i,j+1)) if(mapp[i][j].avail==1) mapp[i][j].nums=mapp[i+1][j].nums;
        }
    }
    cout<<mapp[0][0].nums<<endl;
    return 0;
}

其中底层到上层的思路便是递推,上层到底层的分析便是递归。特别注意递归要注意return具体数值而非函数时的条件,此题中就是x(i,j)==0或i==n&&j==m.

而用递归的方式分析,当(i,j)不通即x(i,j)==0时,return 0;当(i,j)可以走时,f(i,j)将返回f(i+1,j)+f(i,j+1),递归的终点是i==n,j==m,return 1;

递推和递归,就是下推上和上推下的关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值