C++递归算法回溯思想

一、最简单的递归问题(调用函数后无其他代码、不涉及复杂的回溯思想)

递归算法

  1. 递归算法:就是一种函数直接或者间接地调用自身的算法。
  2. 递归算法包括两种情况:函数自己调用自己;两个函数之间互相调用。
    注:(1)有递归边界;(2)每一步执行动作一样;(3)每调用一次规模缩小;(4)结果通过一步步结果层层退出。

在这里插入图片描述

#include<iostream>
using namespace std;
int a=0;
void story();
int main(){
	story();
	return 0;
}
void story(){
	cout<<"小和尚";
	a++;
	if(a<3) story();
	else cout<<"故事讲完了";
}
//答案是:小和尚小和尚小和尚故事讲完了

二、递归函数中的return不是结束整个递归函数哦

在这里插入图片描述
1、递归中的return常用来作为递归终止的条件,但是对于返回数值的情况,要搞明白它是怎么返回的。

2、递归的方式就是自己调用自己,而在有返回值的函数中,上一层的函数还没执行完就调用下一层,因此,当达到递归终止条件时,首先return的是最底层调用的函数,return之后,继续执行上一层调用该函数之后的代码,此时我们看到的是上一层的情况,当上一层剩余的代码执行完之后,表示上一层的函数也结束,此时再返回上上一层,执行递归代码之后的代码,如此往复循环,直到返回到最上层,结束整个递归过程。

3、需要注意的是,上一层执行递归之后的代码的时候,会调用下一层返回的值,也可以理解为在执行上一层代码的时候会调用下一层的实现过程,直到下一层执行完返回一个数值,然后再加上上一层的数值,就构成了上一层return的东西,如此往复。

多说无用,来实战吧!
在这里插入图片描述

三、递归(涉及回溯)举例

学生的年龄问题(递归的执行过程)

 问题描述:有 5 个学生坐在一起,问第 5 个学生多少岁?他说比第 4 个学生大 2岁,问第 4 个学生岁数,他说比第 3 个学生大 2 岁,问第 3 个学生,又说比第 2个学生大 2 岁,问第 2 个学生,说比第 1 个学生大 2 岁,最后问第 1 个学生,他说是 10 岁,请问第 5 个学生多大。
先来个代码

#include<iostream>
using namespace std;
//函数的定义,int值函数的返回值类型为int数据
int age(int n){
	int c;
	if(n==1){
		c = 10;
	}else{
		c = age(n-1) + 2;
	}
	//必须要用rteurn,因为第8行需要用到它的返回值
 	return c;
}
int main(){
	cout<<age(5);
	return 0;
}
//答案是:18

n本身的值没有变(只是把n-1作为实际参数传进去了),但是它作为实际参数传进来age函数里之后n其实变了

递归:c其实就相当于age(n),因为递归函数的返回值是return c;

n=5 c=age(4)+2
n=4 c=age(3)+2
n=3 c=age(2)+2
n=2 c=age(1)+2
n=1 c=10

回溯
n=1时age(1)=10
n=2时age(2)=12
n=3时age(3)=14
n=4时age(4)=16
n=5时age(5)=18

四、涉及较复杂的回溯思想

楼梯问题

1、问题描述:小明上楼梯,一步可以迈 1 个台阶、2 个台阶或者 3 个台阶,现共有 n(1≤n≤30)个台阶,请编程计算他所有可能的走法。
输入样例:4
输出样例:
1 1 1 1
1 1 2
1 2 1
1 3
2 1 1
2 2
3 1

#include<iostream>
using namespace std;
int a[1000];//定义这一步走多少台阶
int index;//定义第几步
void output(){
	for(int i=0;i<index;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;
}
//定义step函数
void step(int n){
	//设置结束的条件,表示可以形成一种走法
	if(n==0){
		output();
		return;
	}
	a[index++]=1;
	step(n-1);
	index--;
	if(n>1){
		a[index++]=2;
		step(n-2);
		index--;
	}
	if(n>2){
		a[index++]=3;
		step(n-3);
		index--;
	}
}
int main(){
	int n;//n表示总台阶数
	cin>>n;
	step(n);//step函数返回n阶台阶的总走法
	return 0;
}

递归:
n=4 a[0]=1 index=1
n=3 a[1]=1 index=2
n=2 a[2]=1 index=3
n=1 a[3]=1 index=4
n=0 output()函数输出1 1 1 1,return之后结束回到上一次递归、且此时
n=1 index=3 不符合两个if语句,又回到上一层递归
n=2 index=2 符合第一个if(n>1),则a(2)=2,index=3 ,n=0,则output()函数输出1 1 2
return之后回到上一次递归,也就是n=2,index=2,不符合if(n>2)回到上一次递归也就是n=3,index=1
符合if(n>1) 则a(1)=2,index=2,step(1),a(2)=1,index=3,step(0),调用output函数输出1 2 1

以此类推~~就不全部举例啦
在这里插入图片描述
其实吧,这个题要是不用编程思想解决的话

可以很简单

比如,用数学思维、找规律哈哈哈
n=1时只有1种走法
n=2时只有2种走法
n=3时只有4种走法
n=1时只有7种走法
变形版斐波那契数列哈哈
f(n)=f(n-1)+f(n-2)+f(n-3)

一句代码完美解决
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面给出一个基于递归回溯算法C++代码实现: ```c++ #include <iostream> #include <vector> #include <stack> #include <ctime> #include <cstdlib> using namespace std; const int N = 1010; int n, m; // 迷宫的行数和列数 int maze[N][N]; // 迷宫地图 int vis[N][N]; // 标记是否访问过某个点 // 定义四个方向 int dx[4] = {-1, 0, 1, 0}; int dy[4] = {0, 1, 0, -1}; // 判断某个点是否在迷宫内 bool inMaze(int x, int y) { return x >= 0 && x < n && y >= 0 && y < m; } // 随机生成迷宫地图 void generateMaze() { srand(time(0)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { maze[i][j] = rand() % 2; // 随机生成0或1 } } maze[0][0] = maze[n - 1][m - 1] = 0; // 迷宫入口和出口不能是障碍物 } // 递归回溯求解迷宫 bool dfs(int x, int y) { if (x == n - 1 && y == m - 1) return true; // 找到出口 vis[x][y] = 1; // 标记当前点为已访问 for (int i = 0; i < 4; i++) { int nx = x + dx[i]; int ny = y + dy[i]; if (inMaze(nx, ny) && maze[nx][ny] == 0 && !vis[nx][ny]) { // 判断是否可以走到下一个点 if (dfs(nx, ny)) return true; // 递归搜索下一个点 } } return false; // 找不到出口 } int main() { cin >> n >> m; generateMaze(); cout << "迷宫地图:" << endl; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cout << maze[i][j] << " "; } cout << endl; } cout << "是否有解:" << (dfs(0, 0) ? "是" : "否") << endl; return 0; } ``` 在这个代码中,我们先随机生成一个迷宫地图,然后从入口开始使用递归回溯算法搜索迷宫。在搜索过程中,我们使用一个二维数组 `vis` 记录每个点是否访问过,确保不会重复访问同一个点。如果找到了出口,则返回 true;否则,返回 false。最后输出是否有解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是彦歆呀嘻嘻哈哈

你的鼓励将是我的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值