算法——回溯模式

        回溯(Backtracking)是一种深度优先搜索(DFS)算法的思想,它用于遍历所有可能的解空间,逐步构建解,并在满足某些条件时进行剪枝,从而减少计算量。回溯算法主要用于组合优化问题,比如求解排列、组合、子集等问题。

回溯算法的核心思想是:

  • 从当前状态开始,尝试每个可能的选择。
  • 如果某个选择不符合要求,则撤销该选择(回溯)。
  • 如果当前解符合要求,则返回当前解。

回溯算法的基本框架

回溯通常采用递归的方式进行实现。回溯的框架一般包括三部分:

  1. 选择:在每一步尝试不同的选择。
  2. 约束:在某些条件下,限制不符合要求的选择。
  3. 撤销:当某个选择导致无法继续时,撤销上一步的选择,返回到之前的状态。

回溯法的常见应用场景

  • 排列问题:给定一组元素,求其所有的排列。
  • 组合问题:从集合中选择若干个元素,满足某些条件,求所有组合。
  • 子集问题:求某个集合的所有子集。
  • N皇后问题:在一个 N×N 的棋盘上放置 N 个皇后,使得它们互不攻击。
  • 数独问题:解决数独游戏。

回溯算法的实现步骤

  1. 定义搜索空间:通常是一个可以逐步生成候选解的状态空间。
  2. 递归:在每一步中,选择一个候选解,并将其作为一个新的状态传递给递归函数。
  3. 剪枝:对于某些不可行的选择,可以提前结束递归,避免不必要的计算。
  4. 回溯:当一个选择完成后,撤销该选择,恢复到上一步状态。

C++ 示例:全排列

问题描述:

        给定一个没有重复数字的数组 nums,返回其所有可能的全排列。

思路:

  • 使用回溯算法,逐步生成排列。
  • 在每一步递归中,尝试所有未被使用的数字,并递归生成剩余的排列。
  • 使用一个 used 数组来记录哪些数字已经被使用。
#include <iostream>
#include <vector>
using namespace std;void backtrack(vector<int>& nums, vector<vector<int>>& result, vector<int>& current, vector<bool>& used) {// 如果当前排列的大小等于数组长度,说明已经找到一个排列if (current.size() == nums.size()) {result.push_back(current);return;}// 遍历数组中的每个元素for (int i = 0; i < nums.size(); i++) {// 如果元素已经被使用过,跳过if (used[i]) continue;// 选择该元素used[i] = true;current.push_back(nums[i]);// 递归生成下一个元素backtrack(nums, result, current, used);// 撤销选择(回溯)used[i] = false;current.pop_back();}
}vector<vector<int>> permute(vector<int>& nums) {vector<vector<int>> result;vector<int> current;vector<bool> used(nums.size(), false);backtrack(nums, result, current, used);return result;
}int main() {vector<int> nums = {1, 2, 3};vector<vector<int>> result = permute(nums);for (auto& perm : result) {for (int num : perm) {cout << num << " ";}cout << endl;}return 0;
}

代码解释

backtrack函数:

  • nums:输入的数字数组。
  • result:存储所有排列结果的二维数组。
  • current:当前构建的排列。
  • used:标记每个数字是否被使用过。

递归过程:

  • 如果 current 的大小等于 nums 的大小,表示当前排列已经完成,加入结果集 result 中。
  • 否则,遍历 nums 中每个数字,尝试将未使用的数字加入 current 中,递归生成剩余的排列。
  • 每次递归后,通过撤销操作 current.pop_back() 和 used[i] = false 回溯到上一状态,继续尝试其他选择。

permute 函数:

  • 这是回溯的入口,初始化 used 数组为 false,然后开始递归。

输出:

  • 打印所有生成的排列。

输出:

1 2 3 
1 3 2 
2 1 3 
2 3 1 
3 1 2 
3 2 1 

C++ 示例:N皇后问题

问题描述:

        给定一个整数 n,求 n 皇后问题的所有解。n 皇后问题是指在一个 n×n 的棋盘上摆放 n 个皇后,使得任何两个皇后都不能在同一行、同一列、同一对角线上。

思路:

  • 使用回溯算法,逐行放置皇后。
  • 使用三个数组来标记每一列、每个主对角线和副对角线是否已经有皇后。
  • 遍历每一行,尝试在每一列放置皇后,检查是否与已放置的皇后冲突。
#include <iostream>
#include <vector>
#include <string>
using namespace std;void solveNQueens(int n, int row, vector<string>& board, vector<vector<string>>& result,vector<bool>& cols, vector<bool>& diag1, vector<bool>& diag2) {if (row == n) {result.push_back(board);return;}for (int col = 0; col < n; ++col) {int d1 = row - col + n - 1;  // 主对角线int d2 = row + col;          // 副对角线if (cols[col] || diag1[d1] || diag2[d2]) continue;  // 如果冲突,跳过// 做选择board[row][col] = 'Q';cols[col] = diag1[d1] = diag2[d2] = true;// 递归调用,处理下一行solveNQueens(n, row + 1, board, result, cols, diag1, diag2);// 撤销选择board[row][col] = '.';cols[col] = diag1[d1] = diag2[d2] = false;}
}vector<vector<string>> solveNQueens(int n) {vector<vector<string>> result;vector<string> board(n, string(n, '.'));  // 初始化棋盘vector<bool> cols(n, false), diag1(2 * n - 1, false), diag2(2 * n - 1, false);solveNQueens(n, 0, board, result, cols, diag1, diag2);return result;
}int main() {int n = 4;vector<vector<string>> result = solveNQueens(n);for (auto& solution : result) {for (auto& row : solution) {cout << row << endl;}cout << endl;}return 0;
}

代码解释

solveNQueens 函数:

  • n:棋盘的大小和皇后的数量。
  • row:当前正在尝试放置皇后的行。
  • board:记录当前棋盘的状态。
  • result:存储所有解决方案。
  • cols、diag1、diag2:分别记录每列、每个主对角线和副对角线是否有皇后。

递归过程:

  • 如果当前行已经放置完所有皇后,则将当前棋盘的状态加入结果。
  • 否则,尝试在当前行的每一列放置一个皇后,递归处理下一行。
  • 如果某个位置已被占用(在同一列、主对角线或副对角线上已有皇后),则跳过。

输出:

        打印所有可能的皇后摆放方式。

输出:

. Q . .
. . . Q
Q . . .
. . Q .Q . . .
. . Q .
. Q . .
. . . Q

总结

        回溯算法适用于那些可以分解成一系列决策的问题,通过逐步构建解并在合适的时机撤销选择,从而探索所有可能的解空间。回溯通常用于求解排列、组合、子集、

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/501079.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker安装(Docker Engine安装)

一、Docker Engine和Desktop区别 Docker Engine 核心组件&#xff1a;Docker Engine是Docker的核心运行时引擎&#xff0c;负责构建、运行和管理容器。它包括守护进程&#xff08;dockerd&#xff09;、API和命令行工具客户端&#xff08;docker&#xff09;。适用环境&#…

【卡通风格的的登录界面】

卡通风格的的登录、注册界面模板&#xff0c;使用uni-app编写&#xff0c;直接复制粘贴即可。 废话不多说&#xff0c;代码如下&#xff1a; login.vue文件 <template><view class"content"><view class"login-form"><view class&quo…

【AI】最近有款毛茸茸AI生成图片圈粉了,博主也尝试使用风格转换生成可爱的小兔子,一起来探索下是如何实现的

应用名称&#xff1a;一键变身毛茸茸小兔子 体验地址&#xff1a;点击跳转体验 模型名称&#xff1a;Kolors&#xff0c;点击跳转 背景 Gitee AI最近发起了一个社群挑战赛。 如果最近你也没什么好点子&#xff0c;想练习又无从下手&#xff0c;怎么办呢&#xff1f; 没关系&a…

重学 Android 自定义 View 系列(十):带指针的渐变环形进度条

前言 该篇文章根据前面 重学 Android 自定义 View 系列(六)&#xff1a;环形进度条 拓展而来。 最终效果如下&#xff1a; 1. 扩展功能 支持进度顺时针或逆时针显示在进度条末尾添加自定义指针图片使用线性渐变为进度条添加颜色效果 2. 关键技术点解析 2.1 进度方向控制的…

Oracle 23ai 图形界面安装

新年的第一篇博客&#xff0c;展示下Oracle 23ai的图形化安装。 主要给大家看下界面&#xff0c;安装的过程与19c没什么不同。 安装前 安装Oracle Database Preinstallation RPM&#xff1a; sudo dnf install oracle-database-preinstall-23aioracle用户有了&#xff1a; …

跳转至系统设置下某个子模块 - 鸿蒙 Harmony

有时候遇到一些需要预授权系统权限才可访问的功能,可以通过如下方式先跳转至系统设置下的某个子页面进行配置,具体如下 code 所示参考: 具体跳转到设置的子设置页面如下也有注释,可供参考使用 /*** 访问系统设置: 子目录* */ static accessSystemSettingSubDirectory(uriKey?:…

el-table 实现纵向多级表头

为了实现上图效果&#xff0c;最开始打算用el-row、el-col去实现&#xff0c;但发现把表头和数据分成两大列时&#xff0c;数据太多时会导致所在格高度变高。但由于每一格数据肯定不一样&#xff0c;为保持高度样式一致&#xff0c;就需要我们手动去获取最高格的高度之后再设置…

2024年度总结答疑

大家好&#xff0c;我是大师兄。在2024年的最后一天&#xff0c;让我们一起来复盘总结&#xff0c;回顾我们在学习和工作中的能力提升、经验教训以及如何在未来做得更好。 过去一年&#xff0c;我们努力提升了学习和工作能力&#xff0c;学习了新的技术和知识&#xff0c;积极参…

flutter组件————Row和Column

Row和Column 在Flutter中&#xff0c;Row 和 Column 是两个非常常用的布局组件&#xff0c;它们用于按照水平或垂直方向排列子组件。 Row Row 组件是一个将子组件沿水平方向&#xff08;从左到右&#xff09;排列的控件。它通常用于创建一行中的多个小部件&#xff0c;比如文…

苹果解锁工具iToolab UnlockGo 中文安装版(附教程+补丁) 2024年6月ios17.4.1可用(记得点赞)解压密码请看文章!!! 评论区获取最新链接

UnlockGo 允许您非常轻松地绕过 iPhone 的密码并获得对设备的完全访问权限。它在以下场景中很有用。 在几分钟内删除 iPhone/iPad 上的各种锁定。 解锁 4 位/6 位密码、Touch ID 和 Face ID 删除没有密码的 iCloud 免费锁 无需密码即可从 iPhone/iPad/iPod 中删除 Apple ID…

[最佳方法] 如何将视频从 Android 发送到 iPhone

概括 将大视频从 Android 发送到 iPhone 或将批量视频从 iPhone 传输到 Android 并不是一件容易的事情。也许您已经尝试了很多关于如何将视频从 Android 发送到 iPhone 15/14 的方法&#xff0c;但都没有效果。但现在&#xff0c;通过本文中的这 6 种强大方法&#xff0c;您可…

driftingblues2

修改网卡配置信息 首先kali终端运行以下命令查看靶机ip 这里我们发现并没有查到靶机的ip&#xff0c;这时我们重启靶机 打开靶机&#xff0c;按下e键&#xff0c;进入到如下界面 将ro替换为rw signie init/bin/bash 替换完毕后&#xff0c;按下Ctrl键X键&#xff0c;进入如下…

数据挖掘——聚类

数据挖掘——聚类 聚类K-meansKNN VS K-meansK-Nearest Neighbors (KNN)K-means K中心算法PAM算法 K-modes算法——解决数据敏感的问题KMeans算法 ——解决初始点选择问题K-中心点层次方法AGNES算法——最小距离单链接全链接平均链接 聚类评估K均值和K中心点的优缺点层次化聚类…

Nginx - 整合lua 实现对POST请求的参数拦截校验(不使用Openresty)

文章目录 概述步骤 1: 安装 Nginx 和 Lua 模块步骤 2: 创建 Lua 脚本用于参数校验步骤 3: 配置 Nginx 使用 Lua 脚本写法二&#xff1a; 状态码写法三 &#xff1a; 返回自定义JSON复杂的正则校验 步骤 4: 测试和验证ngx.HTTP_* 枚举值 概述 一个不使用 OpenResty 的 Nginx 集…

虚拟机中的时统卡功能和性能调优

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…

GXUOJ-算法-补题:22级《算法设计与分析》第一次课堂练习

2.最大子数组和 问题描述 代码解答 #include<bits/stdc.h> using namespace std; const int N1005; int sum,n,a[N]; int res-1;int result(){for(int i0;i<n;i){if(sum<0) suma[i];else{suma[i];resmax(res,sum);}}return res; } int main(){cin>>n;for(i…

信息学奥赛一本通:1311:【例2.5】求逆序对

1311&#xff1a;【例2.5】求逆序对 时间限制: 1000 ms 内存限制: 65536 KB提交数:74572 通过数: 17809 【题目描述】 给定一个序列a1,a2,…,an&#xff0c;如果存在i<j并且ai>aj&#xff0c;那么我们称之为逆序对&#xff0c;求逆序对的数目。 【输入】 第一…

免登录游客卡密发放系统PHP网站源码

源码介绍&#xff1a; 这是一个简单易用的卡密验证系统&#xff0c;主要功能包括&#xff1a; 卡密管理和验证&#xff0c;多模板支持&#xff0c;响应式设计&#xff0c;验证码保护&#xff0c;防刷机制&#xff0c;简洁的用户界面&#xff0c; 支持自定义模板&#xff0c;移…

关于 PPPOE技术的详细解释

PPPoE&#xff08;以太网点对点协议&#xff09;是一种网络协议&#xff0c;它通过光纤将点对点协议&#xff08;PPP&#xff09;封装以实现宽带接入点。PPPoE主要用于ADSL和光纤等宽带接入技术中&#xff0c;它允许多个用户共享同一个交换机连接&#xff0c;同时为每个用户提供…

C# 服务应用研究

文章目录 创建Windows Service项目选中serviceInstaller1组件&#xff0c;查看属性生成和发布服务安装服务卸载服务重新再安装服务停止服务再次卸载服务调试服务 创建Windows Service项目 选中serviceInstaller1组件&#xff0c;查看属性 生成和发布服务 安装服务 卸载服务 重新…