蓝桥杯---第一讲 递归与递推

这篇具有很好参考价值的文章主要介绍了蓝桥杯---第一讲 递归与递推。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

本篇博客主要打卡记录博主学习蓝桥杯C++AB组辅导课的习题第一章节的题目。


Ⅰ. 递归实现指数型枚举

0x00 算法思路

这一道题主要考查 dfs 算法,然后这一道题就是以位置来进行 搜索 当搜索到最后一个位置的时候就可以 收获结果 然后考虑枚举到的位置 可以选择 或者 不选

0x00 代码书写

#include<bits/stdc++.h>

using namespace std;

const int N = 16;

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

0x00 思考总结

这一道题目 就是枚举每一个位置,然后进行选这个数字或者不选这个数字,当枚举到末尾的时候就可以进行收获(打印结果) —> 本质就是枚举每一个位置然后根据选或不选进行的排列组合

Ⅱ. 递归实现排列型枚举

0x00 算法思路

利用一个判断数组st数组,检查是否这个位置的数字我已经使用过了,如果使用过了,就继续,如果没有就直接放到a数组里,递归下一个位置

0x01代码书写

#include<bits/stdc++.h>

using namespace std;

const int N = 11;

int n;
int st[N];//记录这个数字是否被使用过false表示没有,true表示用过
int a[N];//存放数字 方便打印

void dfs(int u)
{
	if(u > n)//(u == n + 1)也是可以的表示枚举到最后一个位置
	{
		for(int i = 1 ; i <= n; ++ i)
			cout << a[i] << " ";
		cout << endl;
		return; 	
	}
	
	for(int i = 1 ; i <= n ; ++ i)
	{
		if(st[i] == false)
		{
			a[u] = i;
			st[i] = true;
			dfs(u + 1);
			st[i] = false; //恢复现场
		}
	}
	return;
}

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

0x02 思考总结

对比上一道题目,上一道是根据选或不选来进行排列组合,这一道题目则是根据n的位置的多少进行排列组合,这里面用到了一个 st 数组来判断这一个数字是否被使用过,从而对这n个位置的数字进行排列组合

Ⅲ. 简单斐波那契

0x00 算法思路

简单的递推公式问题

0x01 代码书写

#include <iostream>
using namespace std;
int main()
{
    int n;
    cin >> n;

    int a = 0, b = 1;

    for (int i = 0; i < n; i ++ )
    {
        cout << a << ' ';
        int c = a + b;
        a = b;
        b = c;
    }

    cout << endl;

    return 0;
}

Ⅳ. 费解的开关

0x00 算法思路

暴力枚举第一行的32—>2的5次方 种情况,然后去统计第一行的五位01串中出现1的数量然后进行turn和step++,
然后枚举除了最后一行的前面四行,遇到 ‘0’ 就可以对 i + 1 行 j 列 进行 turn 操作,从而使得 i,j 这个位置的灯改变成亮。
最后去横扫最后一行,看是否有黑的灯,如果有的话,代表我们的操作是无法完成任务的,所以 输出-1
当发现没有黑的时候,就可以取最小值进行迭代了。

这里复制粘贴一下Acwing上边的疑惑讲解:
1.高票题解代码中的 if (k >> j & 1) 究竟什么意思?

其中,k保存的根本就不是第一行的灯所有可能的状态,不然它第j位都为1了还按它干嘛? k单纯只是保存了第一行按开关的32种方式,与输入数据无关。

且大多数题解代码中都规定了k在二进制下某位为1就代表我们选择按下这一位所在编号的开关,你也可以自己规定k在二进制下某位为0才代表我们选择按下这一位所在编号的开关,这都无所谓。

比如k在二进制下表示为10001,就代表我们选择按第一行编号为0和编号为4的开关,然后对输入数据中第一行这两位执行turn操作。
贴一个Acwing大佬写的超级详细的题解
AcWing 95. 费解的开关(有图超详细,看不懂揍我)

0x01 代码书写

#include<bits/stdc++.h>

using namespace std;

const int N = 6;

char g[N][N], backup[N][N];
int dx[5] = {-1,0,1,0,0}, dy[5] = {0,1,0,-1,0};

void turn(int x,int y)//dfs--->迷宫类模板
{
	for(int i = 0 ; i < 5 ; ++ i)
	{
		int a = x + dx[i], b = y + dy[i];
		if(a < 0 || a >= 5 || b < 0 || b >= 5) continue;
		g[a][b] ^= 1;
	}
}

int main()
{	
	int T;
	cin >> T;
	
	while(T -- )
	{
		for(int i = 0 ; i < 5 ; ++ i)
			for(int j = 0 ; j < 5 ; ++ j)
				cin >> g[i][j];
		
		int res = 10;
		
		for(int op = 0 ; op < 32 ; ++ op)
		{
			memcpy(backup, g , sizeof g);
			int step = 0;
			for(int i = 0 ; i < 5 ; ++ i)
				if(op >> i & 1)
				{
					step ++;
					turn(0, i);
				}
			
			for(int i = 0 ; i < 4 ; ++ i)
				for(int j = 0 ; j < 5 ; ++ j)//对黑的灯进行turn操作
					if(g[i][j] == '0')
					{
						step ++;
						turn(i + 1 , j);
					}
			bool dark = false;
			for(int i = 0 ; i < 5 ; ++ i)//遍历最后一行看是否存在黑着的灯
				if(g[4][i] == '0')
				{
					dark = true;
					break;
				}
				
			if(!dark) res = min(res,step);
			memcpy(g, backup, sizeof g);
		}
		if(res > 6) res = -1;
		cout << res << endl;
	}
		
	return 0;
}

Ⅴ. 递归实现组合型枚举

0x00 算法思路

通过枚举第一个位置和开始的数进行dfs操作,当搜索到最后一个位置的时候就可以收获结果了

0x01 代码书写

#include<bits/stdc++.h>

using namespace std;

const int N = 30;

int n, m;
int st[N];


void dfs(int u, int start)
{
	if(u == m + 1)
	{
		for(int i = 1 ; i <= m ;  ++ i)
			cout << st[i] << " ";
		cout << endl;
		return; 
	}
	
	for(int i = start ; i <= n ; ++ i)
	{
		st[u] = i;
		dfs(u + 1, i + 1);
		st[u] = 0;
	}
}

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

Ⅵ. 带分数

0x00 算法思路

根据 n = a + b / c 变换 成为 : cn = ac + n所以可以先确定ac的值进而确定b的值所以有以下思路:

  1. 枚举a的数值
  2. 枚举c的数值
  3. 判断b是否符合条件

这个题目也用到了全排列的思想—>本节的第二道题目就是全排列题目的代码和思路

0x01 代码书写

#include<bits/stdc++.h>

using namespace std;

const int N = 10;

int n;
bool st[N],backup[N];
int ans;

bool check(int a,int c)
{
	long long b = n * (long long)c - a * c;//防止溢出用long long
	memcpy(backup,st,sizeof st);//用备份操作
	
	if(!a || !b || !c) return false;
	
	while(b)//判断b当中的数字是否被使用过了已经
	{
		int x = b % 10;
		b /= 10;
		if(!x || backup[x]) return false;//被使用过了就返回false
		backup[x] = true;
	}
	
	for(int i = 1 ; i <= 9 ; ++ i)//最后再对abc三个数字所选的数字看看是否选完了0~9个数字
		if(!backup[i])
			return false;
	return true;
}

void dfs_c(int u, int a ,int c)
{
	if(u > 9) return; //超过9个数就可以return
	
	if(check(a,c)) ans ++; //发现组合就可以 ++ans
	
	for(int i = 1 ; i <= 9 ; ++ i)//去确定c的值
	{
		if(!st[i])
		{
			st[i] = true;
			dfs_c(u + 1,a, c * 10 + i);
			st[i] = false;
		}
	}
}

void dfs_a(int u , int a)
{
	if(a >= n) return; //a不能大于n
	if(a) dfs_c(u,a,0);//a不能是0 然后去找c
	
	for(int i = 1 ; i <= 9 ; ++ i)//去确定a的值
	{
		if(!st[i])
		{
			st[i] = true;
			dfs_a(u + 1,a * 10 + i);
			st[i] = false;
		}
	}
	return;
}

int main()
{
	cin >> n;
	
	dfs_a(0, 0);// 去递归搜索 a 一开始选0个数字(用了多少个数),a是0。
	
	cout << ans << endl;
	
	return 0;
}

Ⅶ. 飞行员兄弟

0x00 算法思路

先说结论,在判断是否要对(i, j)位置的把手进行切换时,只需要计算一下第i行和第j列总共7个把手(以下称为(i, j)对应的十字)中闭合的把手数目,如果是奇数个就进行切换,偶数个就不进行切换。(奇数个是该位置的把手进行过切换的充要条件)

因此我们从上到下从左到右顺次的对16个把手进行上述判断。如果判断结果是奇数个那么说明该位置被切换过,进行记录即可。

0x01 代码书写

#include<bits/stdc++.h>

using namespace std;

#define x first
#define y second

const int N = 5;
typedef pair<int,int> PII;
char g[N][N], backup[N][N];

int get(int x, int y)
{
    return x * 4 + y;
}

void turn_one(int x, int y)
{
    if (g[x][y] == '+') g[x][y] = '-';
    else g[x][y] = '+';
}

void turn_all(int x, int y)
{
    for (int i = 0; i < 4; i ++ )
    {
        turn_one(x, i);
        turn_one(i, y);
    }

    turn_one(x, y);
}

int main()
{
	for(int i = 0 ; i < 4 ; ++ i) cin >> g[i];
	
	vector<PII> res;
	
	for(int op = 0 ; op < 1 << 16 ; ++ op)
	{
		vector<PII> temp;
		memcpy(backup, g ,sizeof g);
		
		for(int i = 0 ; i < 4 ; ++ i)
			for(int j = 0 ; j < 4 ; ++ j)
			{
				if(op >> get(i, j) & 1)
				{
					temp.push_back({i, j});
					turn_all(i, j);
				}
			}
		
		bool has_closed = false;
		for(int i = 0 ; i < 4 ; ++ i)
			for(int j = 0 ; j < 4 ; ++ j)
			{
				if(g[i][j] == '+')
					has_closed = true;
			}
		
		if(has_closed == false) 
			if(res.empty() || res.size() > temp.size()) res = temp;
		
		memcpy(g,backup,sizeof g);
	}
	cout << res.size() << endl;
	for(auto& op : res) cout << op.x + 1 << " " << op.y + 1 << endl;
	
	return 0;
}

Ⅷ. 翻硬币

0x00 算法思路

将硬币和目标的样子进行比较,当发现不一样的时候就进行 turn 翻转即可

0x01 代码书写

#include<bits/stdc++.h>

using namespace std;

const int N=110;
char start[N], aim[N];
int n;

void turn(int i)
{
    if(start[i]=='o') start[i]='*';
    else start[i]='o';
}

int main()
{
    cin >> start >> aim;

    n = strlen(start);

    int res=0;
    for(int i = 0; i < n - 1 ; i ++)
    {
        if(start[i] != aim[i])
        {
            turn(i), turn(i+1);
            res ++;
        }
    }

    cout << res << endl;

    return 0;
}

总结

本篇博客主要讲解了递推与递归的算法,也涉及到了 dfs 搜索算法的使用,其实 dfs 算法可以

  1. 先去想dfs的含义,参数的含义
  2. 找到dfs的结束条件进行收获结果
  3. 根据题目要求实现dfs代码

希望自己可以多多练习,后面蓝桥杯辅导课看完就会去看算法提高课继续提升文章来源地址https://www.toymoban.com/news/detail-719851.html

到了这里,关于蓝桥杯---第一讲 递归与递推的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 自动曝光算法(第一讲)

    失业在家无事,想到以后换方向不做自动曝光了,但是自动曝光的工作经验也不能浪费了,准备写一个自动曝光的教学,留给想做自动曝光的小伙伴参考。笔者当时开发自动曝光没有按摄影的av+tv=ev=bv+sv公式弄,而是按正确的增益=目标亮度/当前亮度*当前增益的公式去开发。

    2024年02月06日
    浏览(36)
  • 60题学会动态规划系列:动态规划算法第一讲

    坚持就是胜利 - -  文章目录 1.第N个泰波那切数 2.三步问题 3.使用最小花费爬楼梯 4.解码方法 力扣链接:力扣 泰波那契序列 Tn 定义如下:  T0 = 0, T1 = 1, T2 = 1, 且在 n = 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2 给你整数  n ,请返回第 n 个泰波那契数 Tn 的值。  首先我们分析一下

    2024年02月06日
    浏览(33)
  • 专题一:递推与递归

    递归  递归实现指数型枚举 从 1∼n这 n个整数中随机选取任意多个,输出所有可能的选择方案。 输入格式 输入一个整数 n。 输出格式 每行输出一种方案。 同一行内的数必须升序排列,相邻两个数用恰好 1 个空格隔开。 对于没有选任何数的方案,输出空行。 各行(不同

    2024年02月03日
    浏览(38)
  • 【递推与递归】python例题详解

    文章目录 1、递归实现指数型枚举 2、递归实现排列型枚举 3、递归实现组合型枚举 4、简单斐波那契 5、带分数 6、翻硬币 1、递归实现指数型枚举 题目 从 1∼n这 n个整数中随机选取任意多个,输出所有可能的选择方案。 输入格式 输入一个整数 n。 输出格式 每行输出一种方

    2024年04月25日
    浏览(26)
  • 蓝桥杯备赛 day 1 —— 递归 、递归、枚举算法(C/C++,零基础,配图)

    目录 🌈前言 📁 枚举的概念 📁递归的概念     例题: 1. 递归实现指数型枚举 2. 递归实现排列型枚举 3. 递归实现组合型枚举 📁 递推的概念    例题: 斐波那契数列 📁习题 1. 带分数 2. 反硬币 3. 费解的开关 📁 总结                  这篇文章主要是准备蓝桥杯竞

    2024年02月03日
    浏览(36)
  • LeetCode 0746. 使用最小花费爬楼梯:动态规划(原地)——不用什么从递归到递推

    力扣题目链接:https://leetcode.cn/problems/min-cost-climbing-stairs/ 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼

    2024年02月03日
    浏览(33)
  • 蓝桥杯 第一场算法双周赛题解(前五题)

    题目链接在此😁:第 1 场算法双周赛 - 蓝桥云课 为什么只有前5道题的题解呢?(懂的都懂~🤐) 考察:简单逻辑判断 问题描述 小蓝和小桥玩斗地主,小蓝只剩四张牌了,他想知道是否是“三带一”牌型。 所胃三带一”牌型,即四张手牌中,有三张牌一样,另外一张不与其

    2024年02月08日
    浏览(32)
  • C++Primer——第一讲

    重制C++Primer 目录 一、第一个程序 二、代码  二、题目 我们会从一个C++程序开始,这里默认您已经安装了Dev-C++或其他的IDE软件。 下面这串代码是可以输出“Hello world”的代码。  如果要运行它,就应该先将它编译成程序。先打开IDE,新建一个文件(Ctrl+N): 接着,您可以复

    2024年02月08日
    浏览(28)
  • 第一讲:入门知识笔记

    python 变量无类型,但值里面有类型。 动态类型语言(pythonjavascript) Subtraction reverse 3-digit number 判断两个浮点数是否相等不能直接用== 运算优先级 operation precedence not and or 计算闰年 交换变量 name variable google.github.io/styleguide/pyguide.html python中的权限控制access control 默认成员变量

    2024年01月25日
    浏览(32)
  • 「蓝桥·算法双周赛」第一场公开赛【待补题填坑】

    给定四个字符,判断是否其中有三个相同,另一个与他们不同  二叉树性质问题,不了解二叉树也完全可以做。 要注意的是每次都从第一行的第一个点开始走,给一个字符串按照它走,输出最后的结果就行。 往左走坐标就变成了2*pos-1,往右就变成了2*pos 画个树理解一下就好

    2024年02月07日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包