当前位置: 首页 > news >正文

数据结构与算法:回溯算法约束条件:剪枝详解、示例(C#、C++)与回溯典型例题详解

文章目录

  • 一、约束条件
  • 二、剪枝
  • 三、典型例题
  • 四、常用术语
  • 五、示例
    • N 皇后问题 C# 示例
    • N 皇后问题 C++ 示例
  • 六、常见用用回溯算法解决的问题汇总
    • 组合问题:
    • 图论问题:
    • 棋盘游戏问题:
    • 优化问题:
    • 调度问题:
    • 其他问题:
  • 总结

在这里插入图片描述


回溯算法是一种通过探索所有可能的候选解来找出所有解的算法。在解决一些问题时,我们需要设置一些约束条件,以确保候选解的有效性。这些约束条件在算法中起着非常重要的作用,因为它们定义了一个问题的解空间。通常,我们会使用剪枝技术来减少搜索空间,以提高算法的效率。

本文将详细介绍回溯算法中的约束条件、剪枝技术以及一些典型的回溯问题,还会讨论一些常用的术语。

一、约束条件

在回溯算法中,约束条件是非常重要的,因为它们定义了一个问题的解空间。约束条件必须被满足,一个候选解才被认为是有效的。通常,这些约束条件在算法中被用来进行剪枝,即提前排除那些明显不可能产生解的候选解,从而减少搜索空间。

以 N 皇后问题为例,约束条件如下:

  1. 同一列上的两个皇后不能相互攻击。
  2. 同一斜线(对角线和反对角线)上的两个皇后不能相互攻击。

在 0-1 背包问题中,约束条件如下:

  1. 背包的总容量有限。
  2. 每个物品都有一个重量和价值。

二、剪枝

剪枝是回溯算法中用于减少搜索量的技术。有两种主要的剪枝技术:

  • 前剪枝: 在搜索的早期阶段就排除一些不可能产生有效解的分支。例如,在解决 N 皇后问题时,如果一个皇后已经被放置在某个位置,那么与这个位置在同一行、同一列和同一对角线上的所有其他位置都不能放置皇后。

  • 后剪枝: 在搜索的后期阶段消除那些已经确定不可能产生解的分支。例如,在解决 0-1 背包问题时,如果当前的总重量已经超过背包的容量,那么这个分支可以被剪掉,因为不可能产生一个更优的解。

三、典型例题

1. N 皇后问题: 在 N×N 的棋盘上放置 N 个皇后,使得它们不会相互攻击(即没有两个皇后在同一列、同一行或同一对角线上)。
2. 0-1 背包问题: 给定一组物品,每个物品有一个价值和一个重量,需要选择一些物品放入一个给定容量的背包中,使得背包内物品的总价值最大。
3. 旅行商问题(TSP): 给定一组城市和每两个城市之间的距离,找到一条最短的路径,访问每个城市一次并返回起点。

四、常用术语

1. 候选解: 一个潜在的解,它可能满足所有约束条件。
2. 有效解: 一个候选解,它满足所有约束条件,被认为是实际问题中的解。
3. 搜索空间: 所有可能候选解的集合。
4. 路径/分支: 从初始状态到某个状态的一系列决策的集合。
5. 深度优先搜索(DFS): 一种回溯算法的实现方式,它沿着一个分支深入到不能再深入为止,然后回溯到上一个分叉点继续搜索。

五、示例

下面是 N 皇后问题和 0-1 背包问题的 C# 和 C++ 示例代码。

N 皇后问题 C# 示例

using System;
using System.Collections.Generic;namespace NQueens
{class Program{static void Main(string[] args){int n = 8;SolveNQueens(n);}static void SolveNQueens(int n){int[] board = new int[n];bool[] columns = new bool[n];bool[] diag1 = new bool[2 * n - 1];bool[] diag2 = new bool[2 * n - 1];if (PlaceQueens(board, 0, columns, diag1, diag2)){Console.WriteLine("解决方案:");PrintBoard(board);}else{Console.WriteLine("没有找到解决方案。");}}static bool PlaceQueens(int[] board, int row, bool[] columns, bool[] diag1, bool[] diag2){if (row == board.Length){return true;}for (int col = 0; col < board.Length; col++){if (columns[col] || diag1[row - col + board.Length - 1] || diag2[row + col]){continue;}columns[col] = true;diag1[row - col + board.Length - 1] = true;diag2[row + col] = true;board[row] = col;if (PlaceQueens(board, row + 1, columns, diag1, diag2)){return true;}board[row] = 0;columns[col] = false;diag1[row - col + board.Length - 1] = false;diag2[row + col] = false;}return false;}static void PrintBoard(int[] board){for (int i = 0; i < board.Length; i++){for (int j = 0; j < board.Length; j++){Console.Write(board[j] == i ? "Q " : ". ");}Console.WriteLine();}}}
}

N 皇后问题 C++ 示例

#include <iostream>
#include <vector>using namespace std;void printBoard(const vector<vector<int>>& board) {for (const auto& row : board) {for (int column : row) {cout << column << " ";}cout << endl;}
}bool isSafe(const vector<vector<int>>& board, int row, int col, vector<bool>& columns, vector<bool>& diag1, vector<bool>& diag2) {for (int i = 0; i < row; i++) {if (board[i][col] == 1) {return false;}}for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {if (board[i][j] == 1) {return false;}}for (int i = row, j = col; i < board.size() && j < board[0].size(); i++, j++) {if (board[i][j] == 1) {return false;}}return true;
}bool solveNQueensUtil(vector<vector<int>>& board, int row, vector<bool>& columns, vector<bool>& diag1, vector<bool>& diag2) {if (row == board.size()) {printBoard(board);return true;}for (int col = 0; col < board[0].size(); col++) {if (isSafe(board, row, col, columns, diag1, diag2)) {board[row][col] = 1;columns[col] = true;diag1[row - col + board.size() - 1] = true;diag2[row + col] = true;if (solveNQueensUtil(board, row + 1, columns, diag1, diag2)) return true;board[row][col] = 0;columns[col] = false;diag1[row - col + board.size() - 1] = false;diag2[row + col] = false;}}return false;
}vector<vector<int>> solveNQueens(int n) {vector<vector<int>> board(n, vector<int>(n, 0));vector<bool> columns(n, false);vector<bool> diag1(2 * n - 1, false);vector<bool> diag2(2 * n - 1, false);solveNQueensUtil(board, 0, columns, diag1, diag2);return board;
}int main() {int n = 4;vector<vector<int>> board = solveNQueens(n);return 0;
}

六、常见用用回溯算法解决的问题汇总

回溯算法是一种深度优先搜索的变种,它适用于解决那些需要探索所有可能解的问题。这类问题通常具有递归结构,即一个问题的解空间可以被分解为多个子问题,每个子问题都是原问题的一部分。以下是一些可以用回溯算法解决的问题:

组合问题:

  1. 排列问题(Permutations):给定一组数字,找出所有可能的排列。
  2. 组合问题(Combinations):给定一组数字,找出所有可能的组合。

图论问题:

  1. 最小生成树(MST):在无向图中找到一个包含所有顶点的子图,使得边的总权重最小。
  2. 最大匹配(Maximum Matching):在图中发现最大的匹配集合。
  3. 哈密顿路径(Hamiltonian Path):在图中寻找一条经过所有顶点恰好一次的路径。
  4. 中国邮递员问题(Chinese Postman Problem):寻找一条经过所有边恰好一次的路径,使得总权重最小。

棋盘游戏问题:

  1. 八皇后问题(8 Queens):在 8x8 的棋盘上放置 8 个皇后,使它们互不攻击。
  2. 骑士巡游问题(Knight’s Tour):在棋盘上找到一条骑士访问所有方格恰好一次的路径。

优化问题:

  1. 0-1 背包问题(0-1 Knapsack Problem):给定一组物品,每个物品有一个价值和重量,选择一些物品放入一个给定容量的背包中,使得背包内物品的总价值最大。
  2. 旅行商问题(TSP):寻找一条最短的路径,访问每个城市恰好一次并返回起点。
  3. 表达式求值问题(Evaluate Expression):给定一个包含加、减、乘、除和括号的表达式,计算其值。

调度问题:

  1. 课程调度问题(Course Scheduling):在有限的时间内安排多门课程,满足各种约束条件。
  2. 机器调度问题(Machine Scheduling):在有限的时间内安排多个机器的工作任务,满足各种约束条件。

其他问题:

  1. 子集和问题(Subset Sum):给定一个整数数组和一个目标值,判断是否存在一个子集,其和等于目标值。
  2. 数独问题(Sudoku):在 9x9 的网格中填入数字,使得每行、每列和每个 3x3 子网格中都包含 1 到 9 的所有数字。
  3. 汉诺塔问题(Tower of Hanoi):通过移动盘子从一个塔到另一个塔,同时遵守特定的规则。

回溯算法通过递归地尝试所有可能的解,并在发现当前解不满足要求时回溯到上一个状态,尝试其他可能的解。这种方法适用于解决上述问题,并且可以通过剪枝技术来优化搜索过程,减少不必要的计算。

总结

回溯算法是一种强大的算法,可以用来解决各种问题。通过设置约束条件和使用剪枝技术,我们可以有效地减少搜索空间,提高算法的效率。在实际应用中,回溯算法可以帮助我们解决各种问题,如 N 皇后问题、0-1 背包问题、旅行商问题等。希望这篇博客能帮助你更好地理解回溯算法及其应用。

相关文章:

数据结构与算法:回溯算法约束条件:剪枝详解、示例(C#、C++)与回溯典型例题详解

文章目录 一、约束条件二、剪枝三、典型例题四、常用术语五、示例N 皇后问题 C# 示例N 皇后问题 C 示例 六、常见用用回溯算法解决的问题汇总组合问题&#xff1a;图论问题&#xff1a;棋盘游戏问题&#xff1a;优化问题&#xff1a;调度问题&#xff1a;其他问题&#xff1a; …...

利用sortablejs实现拖拽排序

import Sortable from "sortablejs";created() {//禁止火狐拖拽进行搜索document.body.ondrop function(event){event.preventDefault();event.stopPropagation();}}// 打开对话框的时候调用下openCustomDialog(){this.rowDrop()}// 行拖拽 rowDrop() {this.$nextTi…...

超越AnimateAnyone, 华中科大中科大阿里提出Unimate,可以根据单张图片和姿势指导生成视频。

阿里新发布的UniAnimate&#xff0c;与 AnimateAnyone 非常相似&#xff0c;它可以根据单张图片和姿势指导生成视频。项目核心技术是统一视频扩散模型&#xff0c;通过将参考图像和估计视频内容嵌入到共享特征空间&#xff0c;实现外观和动作的同步。 相关链接 项目&#xff1…...

【MDK5问题】:MDK5无法跳转,并且提示:no browse information available in xxxxx

1、问题&#xff1a; MDK5原来的函数调用可以直接跳转到原函数&#xff0c;但是出现不能跳转原函数的情况&#xff0c;且提示&#xff1a;no browse information available in xxxxx 的情况&#xff1b; 2、解决&#xff1a; 如下图所示&#xff1a;在魔术棒&#xff08;pro…...

OS中断机制-外部中断触发

中断函数都定义在中断向量表中,外部中断通过中断跳转指令触发中断向量表中的中断服务函数,中断指令可以理解为由某个中断寄存器的状态切换触发的汇编指令,这个汇编指令就是中断跳转指令外部中断通过在初始化的时候使能对应的中断服务函数如何判断外部中断被触发的条件根据Da…...

LabVIEW如何进行电磁兼容性测试

电磁兼容性&#xff08;EMC&#xff09;测试是确保电子设备在其工作环境中能够正常运行且不会对其他设备产生有害干扰的关键步骤。LabVIEW作为一种强大的系统设计和开发工具&#xff0c;可以有效地用于电磁兼容性测试。以下是如何使用LabVIEW进行电磁兼容性测试的详细步骤和方法…...

Spring底层架构核心概念总结

Spring底层架构核心概念总结 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; Spring框架是Java企业级应用开发中最受欢迎的框架之一。它以其强大的依赖注入&am…...

hex、bin、elf、s19等文件格式介绍以及格式转换

文章目录 前言一、bin文件二、hex文件数据记录格式扩展线性地址记录(HEX386)格式扩展段地址记录(HEX86)文件结束(EOF)记录三、elf文件四、S19文件五、不同格式之间转换将bin文件转换成hex文件将hex文件转换成bin文件将bin文件转换成s19文件前言 编译器或汇编器将程序的源代码(…...

oracle 窗口函数使用

Oracle 数据库中的窗口函数&#xff08;也称为分析函数或OLAP函数&#xff09;允许您对一组相关的行执行计算&#xff0c;而不是只针对单行。这些函数在数据分析中特别有用&#xff0c;因为它们允许您执行诸如计算移动平均值、累积总和、百分比排名等操作。 以下是一些常用的 …...

【Git】git常用命令

初始化配置 设置用户名和邮箱&#xff0c;来标识身份&#xff0c;方便日后上传GitHub git config --global user.name "xxx" git config --global user.email "xxx"git config --global --list # 存用户名和密码 git config --global --list # 查看配置新…...

【Proteus仿真】【Arduino单片机】寻迹避障蓝牙遥控小车

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使LCD1602液晶&#xff0c;L298电机&#xff0c;直流电机&#xff0c;HC05/06蓝牙模块&#xff0c;HCSR04超声波&#xff0c;红外寻迹模块等。 主…...

嵌入式实验---实验八 ADC电压采集实验

一、实验目的 1、掌握STM32F103ADC电压采集程序设计流程&#xff1b; 2、熟悉STM32固件库的基本使用。 二、实验原理 1、使用STM32F103R6采集可变电阻上的电压信号&#xff0c;并通过计算把当前ADC转换值和电压值显示在LCD1602液晶屏上&#xff1b; 2、对照电压表读数&…...

PHP框架详解:Symfony框架的深度剖析

PHP框架详解&#xff1a;Symfony框架的深度剖析 摘要&#xff1a; Symfony是当前最受欢迎的PHP框架之一&#xff0c;它以其强大的功能和灵活性而闻名。本文将详细介绍Symfony框架的核心概念、架构、组件以及其实践应用&#xff0c;帮助读者深入理解这一框架的优势和使用场景。…...

Linux `screen` 命令详解与使用指南

Linux screen 命令详解与使用指南 在Linux系统中&#xff0c;screen 是一个非常有用的工具&#xff0c;它允许用户在单个终端会话中运行多个进程&#xff0c;并能在会话之间切换。screen 特别适用于远程登录&#xff08;如通过SSH&#xff09;时&#xff0c;确保即使网络连接断…...

CSRF绕过

目录 1. 检查referer referer绕过 2. 检查origin 3. Cookie检查 SameSite 持久性验证 4. Token检查 检测token编码类型,尝试篡改token 绕过token检测 在页面上尝试修改密码, 观察请求的格式. 绕过思路 1. 编写一个js脚本完成以下的任务: 2. 引诱登录的用户触发这…...

如何处理Java中的BufferOverflowException异常?

如何处理Java中的BufferOverflowException异常&#xff1f; 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在Java编程中&#xff0c;BufferOverflowExceptio…...

XMLTomcatHttp协议

XML&Tomcat&Http协议 目录 XML&Tomcat&Http协议 1. xml解析(了解) 1.1 配置文件 1.1.1 配置文件的作用 1.1.2 常见的配置文件类型 1.2 properties文件 1.2.1 文件示例 1.2.2 语法规范 1.3 XML文件 1.3.1 文件示例 1.3.2 概念介绍 1.3.3 XML的基本语…...

Lua优化技巧

常见的Lua优化小技巧 Lua常见优化点&#xff1a;1. 尽量使用局部变量2. table的相关减少对表的访问for循环预分配表空间元表 3. string的相关4. 避免运行时加载编译5. 尽量避免频繁创建临时对象闭包表 Lua常见优化点&#xff1a; 1. 尽量使用局部变量 尽量将变量局部化&#x…...

探索CSS中的cursor鼠标属性

在网页设计中&#xff0c;细节决定成败。CSS的cursor属性是这些细节中的关键一环&#xff0c;它不仅影响着网页的美观&#xff0c;更关乎用户体验。今天&#xff0c;我们就来深入了解一下cursor属性&#xff0c;看看如何通过它来增强网页的交互性。 cursor属性概览 cursor属性…...

图象去噪1-使用中值滤波与均值滤波

1、中值滤波 使用中值滤波去除图像的异常像素点&#xff0c;使用cv2.cv2.medianBlur(img, 3)表示再图像在中值滤波窗口3*3的范围内&#xff0c;从下到大排序&#xff0c;将当前值替换为排序中值&#xff08;如下图所示&#xff09;将56替换为&#xff08;56&#xff0c;66,90,…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...