算法妙妙屋-------2..回溯的奇妙律动

embedded/2025/1/21 10:37:49/

回溯算法是一种用于系统性地搜索和解决问题的算法,它以深度优先搜索(DFS)为基础,用来探索所有可能的解决方案。通过递归地尝试候选解并在必要时回退(即“回溯”),它能够高效地解决许多涉及组合、排列和分割问题的场景。

在这里插入图片描述

核心思想

  1. 递归:回溯算法通常以递归方式实现,每次深入问题的一个分支。
  2. 状态空间树:将问题抽象成一个树形结构,每个节点代表一个部分解或状态。
  3. 剪枝:在探索过程中,提前排除不可能的解以减少计算量。
  4. 回退:当某一条路径无法产生有效解时,返回上一步并尝试其他路径。

典型应用

  • 排列与组合问题:如求全排列、子集生成。
  • 路径搜索问题:如迷宫问题、数独求解。
  • 优化问题:如0/1背包问题。
  • 约束满足问题:如八皇后问题、图着色问题。

算法流程

  1. 选择:选择一个可能的路径或解分支。
  2. 约束检查:判断当前选择是否满足问题的约束条件。
  3. 递归搜索:继续深入探索下一个状态。
  4. 回溯:若当前选择无效,则返回上一步重新选择。

优势与不足

  • 优势:实现简单,适合解决所有可能解的穷举问题。
  • 不足:在问题规模较大时,计算复杂度可能过高,需要结合剪枝优化。

简单示例(伪代码):

def backtrack(path, options):if 满足结束条件:记录结果returnfor option in options:做选择backtrack(新的路径, 剩余选择)撤销选择

通过以上步骤,回溯算法能够在复杂解空间中寻找问题的最优解或所有可能解。

1.单词搜索

题目链接:单词搜索

在这里插入图片描述
解题思路:

  • 1.将整个数组向外扩充一环(避免讨论边缘问题
  • 2.进行深度优先搜索
class Solution {
public:bool dfs(vector<vector<char>>& square, string word,int position,int i,int j,vector<vector<bool>>& check)
{if(position==word.size())return true;if(square[i][j+1]==word[position]&&!check[i][j+1])//判断右{check[i][j+1]=true;if(dfs(square, word,position+1,i,j+1,check)){return true;//这种类型的题目需要return,因为只需查找一个即可满足题意。}else{check[i][j+1]=false;}}if(square[i][j-1]==word[position]&&!check[i][j-1])//判断左{check[i][j-1]=true;if(dfs(square, word,position+1,i,j-1,check)){return true;}else{check[i][j-1]=false;}}if(square[i+1][j]==word[position]&&!check[i+1][j])//判断下{check[i+1][j]=true;if(dfs(square, word,position+1,i+1,j,check)){return true;}else{check[i+1][j]=false;}}if(square[i-1][j]==word[position]&&!check[i-1][j])//判断上{check[i-1][j]=true;if(dfs(square, word,position+1,i-1,j,check)){return true;}else{check[i-1][j]=false;}}return false;
}bool exist(vector<vector<char>>& board, string word) {int row=board.size();int line=board[0].size();vector<vector<bool>>check(row+2,vector<bool>(line+2,false));//初始化二维数组vector<vector<char>>square(row+2,vector<char>(line+2,'0'));for(int i=1;i<row+1;i++){for(int j=1;j<line+1;j++){square[i][j]=board[i-1][j-1];}}for(int i=1;i<row+1;i++){for(int j=1;j<line+1;j++){if(square[i][j]==word[0]){check[i][j]=true;if(dfs(square,word,1,i,j,check)){return true;}check[i][j]=false;  //恢复现场}}}return false;}
};

2.黄金矿工

题目链接:黄金矿工

在这里插入图片描述
解题思路:

  • 枚举矩阵中所有的位置当成起点,来⼀次深度优先遍历,统计出所有情况下能收集到的⻩⾦数的最⼤值即可。
class Solution {
public:int maximum=0;int sum=0;void dfs(vector<vector<int>>& square,int i,int j,vector<vector<bool>>& check)//不需要return,因为要全部遍历一遍才能找到最优解{if(square[i][j+1]!=0&&!check[i][j+1])//判断右{check[i][j+1]=true;sum+=square[i][j+1];dfs(square,i,j+1,check);check[i][j+1]=false;sum-=square[i][j+1];}if(square[i][j-1]!=0&&!check[i][j-1])//判断左{check[i][j-1]=true;sum+=square[i][j-1];dfs(square,i,j-1,check);check[i][j-1]=false;sum-=square[i][j-1];}if(square[i+1][j]!=0&&!check[i+1][j])//判断下{check[i+1][j]=true;sum+=square[i+1][j];dfs(square,i+1,j,check);check[i+1][j]=false;sum-=square[i+1][j];}if(square[i-1][j]!=0&&!check[i-1][j])//判断上{check[i-1][j]=true;sum+=square[i-1][j];dfs(square,i-1,j,check);check[i-1][j]=false;sum-=square[i-1][j];}maximum=max(sum,maximum);//每一次dfs走到底的时候就进行比较,保留最大值}int getMaximumGold(vector<vector<int>>& grid) {int row=grid.size();int line=grid[0].size();vector<vector<bool>>check(row+2,vector<bool>(line+2,false));//初始化二维数组vector<vector<int>>square(row+2,vector<int>(line+2,0));for(int i=1;i<row+1;i++){for(int j=1;j<line+1;j++){square[i][j]=grid[i-1][j-1];}}for(int i=1;i<row+1;i++){for(int j=1;j<line+1;j++){if(square[i][j]!=0){check[i][j]=true;sum+=square[i][j];dfs(square,i,j,check);check[i][j]=false;sum=0;//更换起点,路径长度要归零。}}}return maximum;}
};

注意:黄金矿工和单词搜索不一样,单词搜索只需要找到一个满足题意的路径即可(即找到之后剩下的无需遍历需要return 返回)而黄金矿工需要遍历所有路径来找到最优解,无需return

3.不同路径III

题目链接:不同路径III

在这里插入图片描述
解题思路:

  • 递归结束条件:当前位置的元素值为2,若此时可⾛的位置数量num的值为0,则cnt的值加⼀;
class Solution {
public:int num=0;
int row=0;
int line=0;bool judge(vector<vector<bool>>&check)
{for(int i=1;i<row+1;i++){for(int j=1;j<line+1;j++){  if(check[i][j]==false)//有格子没走过return false;}}return true;//所有格子都走过
}void dfs(vector<vector<int>>& square,int i,int j,vector<vector<bool>>&check)
{if(square[i][j]==2)  //走到终点{if(judge(check)){num++;  //路径数量++;}}if((square[i][j+1]==0||square[i][j+1]==2)&&!check[i][j+1])//判断右{check[i][j+1]=true;dfs(square,i,j+1,check);check[i][j+1]=false;//恢复现场}if((square[i][j-1]==0||square[i][j-1]==2)&&!check[i][j-1])//判断左{check[i][j-1]=true;dfs(square,i,j-1,check);check[i][j-1]=false;//恢复现场}if((square[i+1][j]==0||square[i+1][j]==2)&&!check[i+1][j])//判断下{check[i+1][j]=true;dfs(square,i+1,j,check);check[i+1][j]=false;//恢复现场}if((square[i-1][j]==0||square[i-1][j]==2)&&!check[i-1][j])判断上{check[i-1][j]=true;dfs(square,i-1,j,check);check[i-1][j]=false;//恢复现场}}int uniquePathsIII(vector<vector<int>>& grid) {row=grid.size();line=grid[0].size();int position_row=0;int position_line=0;vector<vector<bool>>check(row+2,vector<bool>(line+2,false));vector<vector<int>>square(row+2,vector<int>(line+2,3));for(int i=1;i<row+1;i++){for(int j=1;j<line+1;j++){square[i][j]=grid[i-1][j-1];if(square[i][j]==1||square[i][j]==-1){if(square[i][j]==1){position_row=i;//找入口的行position_line=j;//找入口的列}check[i][j]=true; //}}}dfs(square,position_row, position_line,check);return num;}
};

在这里插入图片描述


http://www.ppmy.cn/embedded/155750.html

相关文章

MySQL中的GROUP_CONCAT函数将分组后的多个行值合并成一个字符串,并用指定分隔符连接

文章目录 前言什么是GROUP_CONCAT&#xff1f;基本语法 使用示例示例1: 基本用法示例2: 去重并排序 高级应用应用场景示例注意事项 结论表结构1. Orders 表 (订单表)2. Order_Details 表 (订单详情表) 示例数据Orders 表的数据Order_Details 表的数据 使用 GROUP_CONCAT 的查询…

人工智能之数学基础:线性代数中的线性相关和线性无关

本文重点 在线性代数的广阔领域中,线性相关与线性无关是两个核心概念,它们对于理解向量空间、矩阵运算、线性方程组以及人工智能等问题具有至关重要的作用。 定义与直观理解 当存在一组不全为0的数x1,x2,...,xn使得上式成立的时候,那么此时我们可以说向量组a1,a2...,an…

AUTOSAR从入门到精通-【AUTOSAR】AUTOSAR BSW层应用详解

目录 前言 几个高频面试题目 在AUTOSAR系统中如何将BSW模块分配到不同的分区和内核呢? BSW 在多核系统中的分配 错误处理 MCAL及协议栈分配 通信协议栈分配 加密服务分配 安全关键系统中的 BSW 分配 注意事项 算法原理 BSW层通信架构 一、通信驱动 二、通信硬件抽…

AttributeError: ‘super‘ object has no attribute ‘__sklearn_tags__‘

最近用sklearn跑Stacking&#xff0c;基学习器是XGBoost、LightGBM、CatBoost。运行的时候报了标题的这个错误。 应该是sklearn的版本高了&#xff0c;需要降级处理。报错时的版本号是1.6.0 &#xff0c;可以降级到1.5.2。直接运行下面的代码就行。 !pip uninstall -y scikit…

蓝云APP(第三方蓝奏云盘安卓客户端)

蓝云app是一款第三方蓝奏云安卓客户端软件,蓝云安卓版支持手机上传文件,分享链接生成二维码.提供蓝奏云盘官方版所有功能以外的特色功能,例如:全盘文件搜索,蓝奏直链解析下载,自动识别链接,个性化布局等. 特点描述 - 提供更细致化的自定义显示布局 - 支持启用搜索功能&#xf…

R语言的编程范式

R语言的编程范式探讨 引言 R语言作为一种专门用于统计分析和数据可视化的编程语言&#xff0c;近年来得到了广泛的应用。无论是在学术研究、企业分析&#xff0c;还是在数据科学的各个领域&#xff0c;R语言凭借其强大的数据处理能力和丰富的图形化工具&#xff0c;吸引了大批…

【Redis】Redis 集群中节点之间如何通信?

【Redis】Redis 集群中节点之间如何通信&#xff1f; 一背景概述二通信协议Gossip 协议 三通信机制Gossip 消息类型(1).Ping消息(2).Pong消息(3).Meet消息(4).Fail消息 消息传播模式(1).反熵(Anti-entropy)(2).谣言传播(Rumor mongering) 四通信过程通信端口通信频率故障检测与…

《自动驾驶与机器人中的SLAM技术》ch4:预积分学

目录 1 预积分的定义 2 预积分的测量模型 ( 预积分的测量值可由 IMU 的测量值积分得到 ) 2.1 旋转部分 2.2 速度部分 2.3 平移部分 2.4 将预积分测量和误差式代回最初的定义式 3 预积分的噪声模型和协方差矩阵 3.1 旋转部分 3.2 速度部分 3.3 平移部分 3.4 噪声项合并 4 零偏的…