前言:本专栏文章主要是记录蓝桥杯算法学习过程中本人对其的理解和总结 主要以c++进行程序编写 并为现阶段学习c语言不了解c++的同学进行批注方便了解 后会每天更新 欢迎各位大佬指点
刚刚接触算法的同学对于递归还不是很熟悉 递归通常会在我们学习c语言中的函数过程中第一次接触 例如求阶乘的题目 今天我们以指数型枚举为例 来总结递归过程中的算法思想(后会更新排列型枚举和组合型枚举)
递归实现指数型枚举
题目:
从 1∼n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
输入格式:
输入一个整数 n。
输出格式:
每行输出一种方案。
同一行内的数必须升序排列,相邻两个数用恰好 1 个空格隔开。
对于没有选任何数的方案,输出空行。
本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。
数据范围
1≤n≤15
输入样例:
3
输出样例:
3 2 2 3 1 1 3 1 2 1 2 3
该题解决方法中心思想 :利用树的数据结构 采用dfs(深度优先搜索)从而实现递归枚举 我们从1~n依次考虑每个数该不该选 接下来以n=3为例
在图解中 我们设定一个数组st[i] i 表示当前选定的为哪个值
st[1]所在层数为第一层 即我们所选的第一个数字“1” 同时 每一层的st[i]为我们的结点 从第一个结点开始我们分“选”和“不选”的情况 往下推 到st[2]时 判断其no的情况 得出结果后 我们返回结点st[2] 去判断yes的情况 这个过程我们称其为“恢复现场” 以此类推 n=3时 意味着我们树的搜索深度为3
算法核心思想如上图所示 接下来我们进行代码实现:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 16;//避免产生数组越界的情况
int n;
int st[N]; // 状态,记录每个位置当前的状态:0表示还没考虑,1表示选它,2表示不选它
void dfs(int u)//u为当前搜索到第几层
{
if (u > n)//当全部层搜索完后进行输出 我们称这个判断条件为边界条件
{
for (int i = 1; i <= n; i ++ )
if (st[i] == 1)
printf("%d ", i);
printf("\n");
return;
}
st[u] = 2;
dfs(u + 1); // 第一个分支:不选
st[u] = 0; // 恢复现场
st[u] = 1;
dfs(u + 1); // 第二个分支:选
st[u] = 0;
}
int main()
{
cin >> n;//输入n,即c中的scanf
dfs(1);
return 0;
}
建议大家跟着代码逐步分析 在草稿纸上写出结果 更能充分理解代码是如何实现我们图解中的实现思想 同时了解树的基本内容 更能提升理解