递归与递推——递归

递归实现指数型枚举

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

int n;

const int N = 15;
int st[N]; //状态:记录每个位置当前的状态,0表示还没有考虑,1表示选,2表示不选。

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

    st[u] = 2; //不选
    dfs(u + 1);
    st[u] = 0; //恢复现场

    st[u] = 1; //选
    dfs(u + 1);
    st[u] = 0;
}

int main()
{
    cin >> n;

    dfs(1);

    return 0;
}

递归实现排列型枚举

在这里插入图片描述

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

const int N = 10;

int n;
int st[N];
bool used[N]; //标记某个数是否枚举过

void dfs(int u) //枚举第u个位置
{
    if(u > n)
    {
        for(int i = 1; i <= n; i ++ )
            cout << st[i] << ' ';
            puts(" ");

            return ;
    }

    for(int i = 1; i <= n; i ++ )
    {
        if(!used[i])
        {
            st[u] = i;
            used[i] = true; 
            dfs(u + 1);

            st[u] = 0; //恢复现场
            used[i] = false;
        }
    }
}
int main()
{
    cin >> n;

    dfs(1);

    return 0;
}

递归实现组合型枚举

在这里插入图片描述

输入样例:
5 3
输出样例:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 30;
int n,m;
int way[N];

void dfs(int u,int start)
{
    if(u == m + 1) //边界:枚举到最后一个位置
    {
        for(int i = 1; i <= m; i ++ )
            cout << way[i] << ' ';
        puts(" ");
        return;
    }
    
    for(int i = start; i <= n; i ++ )
    {
        way[u] = i;
        dfs(u + 1,i + 1);
        way[i] = 0; //恢复现场,用0表示空
        //这条语句可以省略,因为下一次枚举,后面的值会覆盖已经有的值
    }
    
}

int main()
{
    cin >> n >> m;
    
    dfs(1,1); //从第一个位置开始,从1开始枚举
    
    return 0;
}

优化
剪枝:提前发现递归搜索树中某些分支是无解的,提前把它剪掉。
例如:我们正在选第u个数,那么已经选的就是u-1个数,而后面可以从start选到n。那么,如果把start到n全部选上还不够m个数的话,就是无解的。即 u - 1 + n - start + 1 < m,即 u + n - start < m;
只需加一条语句 if(u + n - start < m) return即可,会发现,明显快了很多。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值