【AcWing】蓝桥杯辅导课-递归与递推

目录

1、递归

1.1 递归实现指数型枚举

1.2 递归实现排列型枚举

1.3 递归实现组合型枚举

1.4 带分数

方法一

方法二

2、递推

2.1 简单斐波那契

2.2 费解的开关

2.3 翻硬币

2.4 飞行员兄弟

方法一

方法二


1、递归

递归就是在函数内部自己调用自己
我们以递归的形式来实现斐波那契数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89

#include<iostream>
using namespace std;

int fib(int n)
{
    if(n == 1) return 0;
    if(n == 2) return 1;
    return fib(n - 1) + fib(n - 2);
}

对于每一个递归,都可以画出一颗递归搜索树

有n步,每一步都会分成两个分支,所以时间复杂度是O(2^n)

1.1 递归实现指数型枚举

92. 递归实现指数型枚举 - AcWing题库

这道题中,n是15,所以我们可以猜测时间复杂度是O(2^n)或O(n*2^n)

这道题我们可以采用DFS来做,对于DFS来说,搜索顺序非常重要。找到一个顺序,可以不重不漏地把每种方案找出。在这道题中,我们可以开一个数组,数组的1-n位,依次考虑每个数选或不选

对于位置1, 2, 3, ..., n,都有选和不选两种情况,所以是2^n。并且还要将每种方案输出,所以,时间复杂度是O(n*2^n)

#include<iostream>
using namespace std;

const int N = 20;

int n, a[N];

void dfs(int u)
{
    if(u > n)
    {
        for(int i = 1;i <= n;i ++)
            if(a[i] == 1)
                cout << i << " ";
        cout << endl;
        return ;
    }
    a[u] = 2;
    dfs(u + 1);
    a[u] = 1;
    dfs(u + 1);
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    dfs(1);
    return 0;
}

1.2 递归实现排列型枚举

94. 递归实现排列型枚举 - AcWing题库

这道题也是采用DFS做。
顺序1:依次枚举每个数放到那个位置
顺序2:依次枚举每个位置放那个数
我们采用的是顺序2来做

#include<iostream>
using namespace std;

const int N = 15;

int n, a[N];
bool st[N];

void dfs(int u)
{
    if(u > n)
    {
        for(int i = 1;i <= n;i ++)
            cout << a[i] << " ";
        cout << endl;
        return ;
    }
    for(int i = 1;i <= n;i ++)
        if(!st[i])
        {
            st[i] = true;
            a[u] = i;
            dfs(u + 1);
            st[i] = false;
        }
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    dfs(1);
    return 0;
}

1.3 递归实现组合型枚举

93. 递归实现组合型枚举 - AcWing题库

排列是考虑顺序的,1 2 3和1 3 2是不一样的
组合是不考虑顺序的,1 2 3和1 3 2是一样的
所以,在递归实现组合型枚举时,需要规定一个顺序,这样在枚举时就可以保证不重复了,这里以升序为例。也就是说,对于1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1我们只枚举1 2 3即可
顺序:从前往后,依次枚举每个位置是几
为了有序,我们只需要时刻保持相邻两个位置的数有序即可
排列类型枚举需要一个bool类型的判重数组,而组合类型枚举不需要,因为只需要保证顺序即可

#include <iostream>

using namespace std;

const int N = 30;

int n, m;
int way[N];

void dfs(int u, int start) // u表示现在要填序列的第几位,start表示这一位可以从那个数开始填
{
    if (u == m + 1)
    {
        for (int i = 1; i <= m; i ++ ) cout << way[i] << " ";
        cout << endl;
        return;
    }

    for (int i = start; i <= n; i ++ )
    {
        way[u] = i;
        dfs(u + 1, i +
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值