数据结构算法-回溯算法技术点

基本描述

当一个问题无法的时候,就需要回退一步 ,这就是回溯法
当然可以理解为传说中的后悔药 and 撤销;
这里需要说明 :游戏里经常使用回溯法 王者荣耀被对方这个老六 用某种组合技能 给挂了,是不是回到重生点 ?
你在社交软件里如果发送了你认为错误的信息的时候,需要点击撤销按钮 删除撤销的信息

算法的核心思想

当某个子问题, 无法继续 就得回退到前子问题 ,当然前子问题需要保存,用到的时候 回复,直到问题全部解决完毕

  • 问题:需要解决的需求
  • 保存前子问题:
    算法的思维导图模式在这里插入图片描述

回溯算法的伪代码

回溯算法(解空间, 问题) {

		往解空间添加子问题
	while (解空间还有数据) {
	需要回溯子问题 = 获取刚刚添加的新数据;
		if (具体子问题 ==) {
					添加新的子问题
						进入下一次循环
			}
		子问题操作
			删除解空间的数据或者退出
	}
}

回溯法 - 应用

迷宫求解

在这里插入图片描述
一共有多少种解法
首先在当前的位置设置为2(参考下面的流程图)

首先是向左走,如果能走得动设置迷宫的地图 并且更新这个位置
再向上走 ,如果能走得动设置迷宫的地图 并且更新这个位置
再向下走 ,如果能走得动设置迷宫的地图 并且更新这个位置
再向右走 ,如果能走得动设置迷宫的地图 并且更新这个位置
重复执行直到找到出口

迷宫求解流程图:
在这里插入图片描述

通过流程图可以清晰的每一个步骤

来看看代码吧:

迷宫求解 -声明

#ifndef __MAZESOLVING_H__
#define __MAZESOLVING_H__

struct MazePosition {
	int x;
	int y;
};


const int MapRow = 6;
const int MapCol = 6;

//迷宫求解  参数:迷宫地图 ,迷宫入口位置
void MazeSolving(const int Map[MapRow][MapCol],const MazePosition& MazeEntrance);


#endif

迷宫求解 -实现

#include "MazeSolving.h"
#include"SeqStack.h"
#include<iostream>
#include<cassert>
using namespace std;

const int MazeMapRow = MapRow;
const int MazeMapCol = MapCol;
struct Maze{
	int map[MazeMapRow][MazeMapCol];
};


static void initMaze(Maze& maze,const int Map[MapRow][MapCol])  {

	auto &mazeMap = maze.map;
	for (int i = 0,j=0; i < MapRow; i++) {
		for (j = 0; j < MapCol; j++) {

			mazeMap[i][j] = Map[i][j];
		}

	}
}

static void showMaze(const Maze& maze) {

	cout << "迷宫:" << endl;

	for(auto &row: maze.map){
	
		for (auto& col:row){
			cout << "\t" << col << " ";
		}
		cout << endl;
	}
	cout << endl;
}
//检查入口是否合法
static bool CheckEntrance(const Maze& Maze, const MazePosition& current) {



	const int Zreo = 0;
	const int Once = 1;
	const int Row = MazeMapRow - 1;
	const int Col = MazeMapCol - 1;
	auto& MazeMap = Maze.map;
	const int& currentX = current.x;
	const int& currentY = current.y;

	return (((currentX == Zreo || currentX == Row) || (currentY == Zreo || currentY == Col)) && (MazeMap[currentX][currentY] == Once));
}

static bool CheckIsExit(Maze& Maze, const MazePosition& current, const MazePosition& MazePos) {

	const int Zreo = 0;
	const int Row = MazeMapRow - 1;
	const int Col = MazeMapCol - 1;

	const int& currentX = current.x;
	const int& currentY = current.y;
	const int& MazePosX = MazePos.x;
	const int& MazePosY = MazePos.y;

	return ((currentX != MazePosX || currentY != MazePosY) && ((currentX == Zreo || currentX == Row) || (currentY == Zreo || currentY == Col)));
}


static bool CheckNextPass(const Maze& Maze, const MazePosition& current, const MazePosition& next) {
	
	bool ret = false;
	const int Zreo = 0;
	const int Row = MazeMapRow ;
	const int Col = MazeMapCol ;
	const int Once = 1;
	const int& currentX = current.x;
	const int& currentY = current.y;
	const int& NextX = next.x;
	const int& NextY = next.y;
	const int& value = Maze.map[NextX][NextY];

	if ((ret = ((NextX == currentX) && (NextY == currentY + 1 || NextY == currentY - 1)
		|| (NextY == currentY) && (NextX == currentX + 1 || NextX == currentX - 1)))) {

		ret = (((NextX >= Zreo || NextX < Row) || (NextY >= Zreo || NextY < Col)) && (value == Once));
	}
	return ret;
}



static bool FindMazeExit(Maze &Maze ,const MazePosition& MazeEntrance,MazePosition & MazeExitPos) {

	assert(CheckEntrance(Maze, MazeEntrance) == true);

	bool ret = false;
	SeqStack stack;
	initStack(stack);

	MazePosition current = MazeEntrance;
	MazePosition Next;
	auto& MazeMap = Maze.map;
	//走了一步
	MazeMap[current.x][current.y] = 2;

	push_Stack(stack, current);

	while (!emptyStack(stack))	{
		current = TopStack(stack);
		//检测当前是否能退出
		if (CheckIsExit(Maze,current, MazeEntrance)){
			MazeExitPos = current;
			ret = true;
			break;
		}

		//检测左边
		//检测下一个位置是否可以走
		Next = current;
		Next.y = current .y- 1;
		//如果可以走
		if (CheckNextPass(Maze,current,Next)){
			//更新地图
			MazeMap[Next.x][Next.y] = MazeMap[current.x][current.y] + 1;
			
		   //将下一个位置入栈
			push_Stack(stack, Next);

		  //进入下一次循环
			continue;
		}
		
		//检测上边
		//检测下一个位置是否可以走
		Next = current;
		Next.x = current.x - 1;
		//如果可以走
		if (CheckNextPass(Maze, current, Next)) {
			//更新地图
			MazeMap[Next.x][Next.y] = MazeMap[current.x][current.y] + 1;

			//将下一个位置入栈
			push_Stack(stack, Next);

			//进入下一次循环
			continue;
		}

	    //检测下边
		//检测下一个位置是否可以走
		Next = current;
		Next.x = current.x + 1;
		//如果可以走
		if (CheckNextPass(Maze, current, Next)) {
			//更新地图
			MazeMap[Next.x][Next.y] = MazeMap[current.x][current.y] + 1;

			//将下一个位置入栈
			push_Stack(stack, Next);

			//进入下一次循环
			continue;
		}

		//检测右边
	   //检测下一个位置是否可以走
		Next = current;
		Next.y = current.y + 1;
		//如果可以走
		if (CheckNextPass(Maze, current, Next)) {
			//更新地图
			MazeMap[Next.x][Next.y] = MazeMap[current.x][current.y] + 1;

			//将下一个位置入栈
			push_Stack(stack, Next);

			//进入下一次循环
			continue;
		}

		//删除栈顶数据
		pop_Stack(stack);

	}
	
	destroyStack(stack);

	return ret;
}

void MazeSolving(const int Map[MapRow][MapCol], const MazePosition& MazeEntrance) {

	Maze maze;
	initMaze(maze,Map);

	showMaze(maze);

	MazePosition MazeExitPos;
	if (FindMazeExit(maze, MazeEntrance,MazeExitPos)){
		showMaze(maze);	
		cout << "找到迷宫的出口了  出口为:[" << MazeExitPos.x << "行," << MazeExitPos.y <<"列]" << endl;
	}
	else {
		cout << "未找到迷宫出口" << endl;
	}
}

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小森程序员

若能帮助到你,小费自愿付费

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

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

打赏作者

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

抵扣说明:

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

余额充值