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

回溯算法及其应用

回溯是一种常见的算法思想,用于解决许多优化问题。该算法的核心思想是穷举所有可能的解决方案,然后通过剪枝来减少不必要的计算,以获得最优解。

回溯算法常用于求解组合、排列、子集和等问题。通常情况下,回溯算法需要递归地搜索问题的解空间,并在搜索过程中记录可能的解决方案。如果找到了一个可行的解决方案,则返回该解决方案。如果没有找到解决方案,则回溯并尝试其他可能的解决方案,直到所有可能的解决方案都被尝试过。

以下是一个简单的JavaScript回溯算法示例,用于寻找一个数列中所有可能的子集:

function subsets(nums) {const res = [];const backtrack = (start, path) => {res.push(path.slice());for (let i = start; i < nums.length; i++) {path.push(nums[i]);backtrack(i + 1, path);path.pop();}}backtrack(0, []);return res;
}console.log(subsets([1, 2, 3])); // [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]

在此示例中,我们定义了一个backtrack函数来递归搜索解空间。start参数表示在搜索过程中从哪个位置开始搜索,path参数表示当前搜索路径上的所有元素。在每个递归调用中,我们首先将当前路径添加到结果数组res中,然后从start位置开始循环遍历剩余元素,并尝试将其添加到当前路径中。完成搜索后,我们需要回溯并尝试其他可能的解决方案。

接下来,我们来看一个更实际的应用场景:解决数独问题。

数独是一种流行的逻辑游戏,玩家需要在一个九宫格中填入数字,保证每一行、每一列和每一个小九宫格中的数字都不重复。数独问题可以用回溯算法来求解。下面是一个JavaScript实现的示例代码:

function solveSudoku(board) {const ROWS = 9, COLS = 9;const BOXES = [[0, 0], [0, 3], [0, 6],[3, 0], [3, 3], [3, 6],[6, 0], [6, 3], [6, 6]];const isValid = (row, col, num) => {for (let i = 0; i < ROWS; i++) {if (board[i][col] === num) return false;if (board[row][i] === num) return false;}const boxRow = Math.floor(row / 3) * 3;const boxCol = Math.floor(col / 3) * 3;for (let i = boxRow; i < boxRow + 3; i++) {for (let j = boxCol; j < boxCol + 3; j++) {if (board[i][j] === num) return false;}}return true;}const backtrack = (row, col) => {if (col === COLS) {row++;col = 0;}if (row === ROWS) {return true;}if (board[row][col] !== '.') {return backtrack(row, col + 1);}for (let num = 1; num <= 9; num++) {if (isValid(row, col, String(num))) {board[row][col] = String(num);if (backtrack(row, col + 1)) {return true;}board[row][col] = '.';}}return false;}backtrack(0, 0);
}const board = [['5', '3', '.', '.', '7', '.', '.', '.', '.'],['6', '.', '.', '1', '9', '5', '.', '.', '.'],['.', '9', '8', '.', '.', '.', '.', '6', '.'],['8', '.', '.', '.', '6', '.', '.', '.', '3'],['4', '.', '.', '8', '.', '3', '.', '.', '1'],['7', '.', '.', '.', '2', '.', '.', '.', '6'],['.', '6', '.', '.', '.', '.', '2', '8', '.'],['.', '.', '.', '4', '1', '9', '.', '.', '5'],['.', '.', '.', '.', '8', '.', '.', '7', '9']
];solveSudoku(board);console.log(board);

在这个示例代码中,我们首先定义了一些常量和辅助函数。isValid函数用于检查当前位置是否可以填入指定的数字。backtrack函数则是回溯算法的核心,它用于递归地搜索解空间,并在搜索过程中记录可能的解,然后验证这个解是否符合要求。如果符合要求,则继续搜索下一步可能的解;如果不符合要求,则回溯到上一步,重新选择其他可能的解。

在数独问题中,我们从左到右、从上到下依次遍历每一个格子。对于每一个空格,我们依次尝试填入1到9的数字,并检查填入的数字是否合法。如果合法,则继续搜索下一个空格;如果不合法,则回溯到上一个空格重新尝试填入其他数字。

通过回溯算法,我们可以找到数独问题的一个解,如果数独问题有多个解,回溯算法也可以找到所有的解。在这个示例代码中,我们使用了递归的方式实现回溯算法。当找到一个解时,函数返回true,表示已经找到解;当所有可能的解都被尝试过后,函数返回false,表示没有找到解。

回溯算法的时间复杂度一般较高,因为它需要搜索所有可能的解空间。对于数独问题,回溯算法的时间复杂度取决于解的数量,一般来说解的数量不会太多,因此回溯算法是一个有效的求解方法。

总之,回溯算法是一种常用的求解问题的方法,它可以用于求解各种类型的问题,包括数独、八皇后、0/1背包等等。在实际应用中,我们可以结合其他算法和数据结构来优化回溯算法的效率,例如剪枝、记忆化搜索等。

下面是完整的示例代码:

// 数独问题的解决函数
function solveSudoku(board) {// 遍历数独表格for (let i = 0; i < 9; i++) {for (let j = 0; j < 9; j++) {// 如果当前格子为空if (board[i][j] === ".") {// 尝试填入1到9的数字for (let num = 1; num <= 9; num++) {// 如果填入的数字合法if (isValid(board, i, j, num)) {// 填入数字board[i][j] = num.toString();// 递归调用解决函数if (solveSudoku(board)) {// 如果找到解,则返回truereturn true;} else {// 如果没有找到解,则回溯board[i][j] = ".";}}}// 如果尝试了所有的数字都无法得到解,则返回falsereturn false;}}}// 如果遍历完整个数独表格,都没有返回true,则说明已经找到解return true;
}// 检查填入的数字是否合法
function isValid(board, row, col, num) {// 检查行是否合法for (let i = 0; i < 9; i++) {if (board[row][i] === num.toString()) {return false;}}// 检查列是否合法for (let j = 0; j < 9; j++) {if (board[j][col] === num.toString()) {return false;}}// 检查3x3方格是否合法let boxRow = Math.floor(row / 3) * 3;let boxCol = Math.floor(col / 3) * 3;for (let i = boxRow; i < boxRow + 3; i++) {for (let j = boxCol; j < boxCol + 3; j++) {if (board[i][j] === num.toString()) {return false;}}}// 如果行、列、3x3方格都没有重复的数字,则返回truereturn true;
}// 测试代码
let board = [["5", "3", ".", ".", "7", ".", ".", ".", "."],["6", ".", ".", "1", "9", "5", ".", ".", "."],[".", "9", "8", ".", ".", ".", ".", "6", "."],["8", ".", ".", ".", "6", ".", ".", ".", "3"],["4", ".", ".", "8", ".", "3", ".", ".", "1"],["7", ".", ".", ".", "2", ".", ".", ".", "6"],[".", "6", ".", ".", ".", ".", "2", "8", "."],[".", ".", ".", "4", "1", "9", ".", ".", "5"],[".", ".", ".", ".", "8", ".", ".", "7", "9"],
];
if (solveSudoku(board)) {console.log(board);
} else {console.log("No solution");
}

上述代码实现了一个求解数独问题的函数solveSudoku上述代码实现了一个求解数独问题的函数solveSudoku,该函数使用了回溯算法的思想。具体实现过程如下:

  1. 遍历数独表格的每一个格子,如果当前格子为空,则尝试填入1到9的数字。
  2. 如果填入的数字合法(即在行、列、3x3方格中都没有重复的数字),则将该数字填入当前格子。
  3. 递归调用solveSudoku函数,继续填写下一个空格。
  4. 如果在下一个空格中找到了解,则返回true,表示已经找到解。
  5. 如果在下一个空格中没有找到解,则回溯到当前格子,将当前格子重新设为".",并尝试填入下一个数字。
  6. 如果尝试了所有的数字都无法得到解,则返回false。

相关文章:

回溯算法及其应用

回溯是一种常见的算法思想&#xff0c;用于解决许多优化问题。该算法的核心思想是穷举所有可能的解决方案&#xff0c;然后通过剪枝来减少不必要的计算&#xff0c;以获得最优解。 回溯算法常用于求解组合、排列、子集和等问题。通常情况下&#xff0c;回溯算法需要递归地搜索…...

如何一步步打造完美的成绩查询系统平台?

想要搭建一个高效的在线发布成绩查询系统平台&#xff0c;首先需要了解哪些技术和工具是必备的。本文将为您介绍一些主流的技术和工具&#xff0c;帮助您快速搭建一个稳定、安全、易用的成绩查询系统。 想要制作在线成绩查询系统平台有两种方式&#xff0c;第一种是直接使用易…...

P1026 [NOIP2001 提高组] 统计单词个数

题目描述 给出一个长度不超过 200200 的由小写英文字母组成的字母串&#xff08;该字串以每行 2020 个字母的方式输入&#xff0c;且保证每行一定为 2020 个&#xff09;。要求将此字母串分成 &#xfffd;k 份&#xff0c;且每份中包含的单词个数加起来总数最大。 每份中包含…...

CTFHub | eval执行

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习&#xff0c;实训平台。提供优质的赛事及学习服务&#xff0c;拥有完善的题目环境及配套 writeup &#xff0c;降低 CTF 学习入门门槛&#xff0c;快速帮助选手成长&#xff0c;跟随主流比赛潮流。 0x01 题目描述…...

IP协议头

IP 4位版本号&#xff08;version&#xff09;4位头部长度&#xff08;header length&#xff09;8位服务类型&#xff08;Type Of Service&#xff09;16位总长度&#xff08;total length&#xff09;16位标识&#xff08;id&#xff09;3位标志字段13位分片偏移&#xff08;…...

【xxl-job定时任务框架详解】

一,分布式任务调度 基本概念 分布式任务调度是一种用于在分布式环境中调度和执行任务的技术。在分布式系统中,由于存在多台服务器、多个进程和线程并行执行,因此需要一种机制来协调和管理任务的执行,避免任务冲突、重复执行、负载不均衡等问题。分布式任务调度通常由一个…...

7、在vscode上利用cmake构建多文件C++工程

文章目录 &#xff08;1&#xff09;创建如下工程文件夹&#xff1a;其中头文件放在include文件夹中&#xff0c;源文件放在src文件夹中&#xff08;2&#xff09;在vscode上打开工程文件夹&#xff0c;在对应的文件夹内建立相应的文件1&#xff09;目录结构2&#xff09;各文件…...

Linux操作系统网络模块

Linux操作系统的网络模块是负责网络通信的核心部分。它通过实现各种协议和算法&#xff0c;使得计算机能够在网络中进行数据交换和通信。网络模块主要包括以下几个方面的功能&#xff1a; &#xff08;1&#xff09;IP协议栈&#xff1a;负责处理网络层的数据包&#xff0c;实…...

不同批次板子采集到的传感器压力值不同

问题描述&#xff1a; M340B空压机主控板在接正常压力气源时&#xff0c;显示屏显示压力值过高并报警。 问题排查&#xff1a; 确认可能的故障点&#xff1a;压力传感器、硬件电路&#xff08;供电电路、分压电路、ADC采样电路等&#xff09;、单片机、软件&#xff1b; 排…...

设计模式--原型模式

目录 基本介绍 传统方式克隆 原型模式改进 浅拷贝和深拷贝 浅拷贝的介绍 深拷贝的介绍 原型模式的注意事项和细节 基本介绍 (1) 原型模式(prototype模式): 用原型实例指定创建对象的种类 并且通过拷贝这些原型 创建新的对象 (2) 原型模式是一种创建型设计模式 允许一个…...

C++智能指针shared_ptr详解

智能指针shared_ptr详解 一、简介二、底层原理2.1、引用计数2.2、shared_ptr的构造和析构2.3、shared_ptr的共享和拷贝2.4、循环引用问题 三、shared_ptr的使用3.1、创建一个shared_ptr3.2、共享一个shared_ptr3.3、使用删除器3.4、解除关联 四、使用示例总结 一、简介 C智能指…...

家政服务APP小程序开发功能详解

随着人们生活水平的提高&#xff0c;对家政服务的要求也越来越高。而传统的到家政公司寻找服务人员的方法显然已经无法满足人们需求&#xff0c;取而代之的是线上预约家政服务。家政服务App小程序软件可以满足用户在线预约&#xff0c;还可以根据自己的需求定制家政服务、选择家…...

【C++】deque的实现原理简单介绍

前言 deque被称为双端队列&#xff0c;它的出现主要是为了结合vector和list的优点并减小它们的缺点&#xff0c;实际上deque确实结合了vector和list的优点减小了它们的缺点&#xff0c;但是它的结合也让它自己的优点没有原始的vector和list那么极致&#xff0c;导致deque变得很…...

UWB隧道人员定位技术应用,施工作业安全精准保障

隧道施工的安全不仅关系到工程项目的质量和施工效率&#xff0c;也关系到我国的资金安全、施工人员和人民的生命财产安全。如何有效加强隧道施工的安全管理能力&#xff0c;成为隧道施工企业管理者最关心的问题。国家铁道局在《关于加强铁路隧道工程安全工作的若干意见》中指出…...

15.2 矩阵链乘法

1.代码 public class MatrixChainMultiplication {public static void main(String[] args) { // 在该代码中&#xff0c;我们首先创建了两个n * n的矩阵m和s&#xff0c;分别用于记录最优值和分割点。 其中m 矩阵 通过i j 来显示在i到j的矩阵链中最优解 // // …...

向隐形冠军学习:聚焦人效,用时间管理提效益

注&#xff1a; 本文来源于盖雅工场联合创始人兼CEO 章新波 在2023狮山论坛“ 向隐形冠军学习&#xff1a; 聚焦人效&#xff0c;用时间管理提效益 ”的主题分享。 文&#xff5c;章新波 整理 &#xff5c;盖雅学苑 在人力资源行业以及各大企业&#xff0c;「人效」这个词…...

Protocol Buffers Go Generated Code Guide

Protocol Buffers Go 代码生成指南 本主题准确描述了协议缓冲区编译器为任何给定的协议定义生成的Go代码。 编译器调用 协议缓冲区编译器需要一个插件来生成Go 代码。使用Go 1.16或更高版本安装&#xff0c;方法是运行&#xff1a; go install google.golang.org/protobuf/…...

Python VTK STL 映射三维模型表面距离

目录 前言&#xff1a; 效果&#xff1a; 实现步骤&#xff1a; Code: 前言&#xff1a; 本文介绍了Python VTK映射三维模型表面距离&#xff0c;通过如何使用VTK计算两个三维模型(stl)的表面距离&#xff0c;并将其距离值以颜色映射到模型&#xff0c;可用于对比 两相模型…...

C# 异常处理机制和常见的异常类型

在 C# 中&#xff0c;异常处理是一个非常重要的概念&#xff0c;它可以让我们在程序发生错误时进行有效的处理&#xff0c;使程序具备更好的鲁棒性。C# 异常处理机制基于 try-catch-finally 语句块&#xff0c;其基本用法如下&#xff1a; try {// 可能会抛出异常的代码 } cat…...

【0187】客户端身份验证配置文件视图之pg_hba_file_rules

文章目录 1. 客户端身份验证配置文件视图2. 视图效果相关阅读: 【0179】配置PostgreSQL以允许远程连接 【0180】PG内核通过pg_hba.conf完成客户端认证(1) 【0181】PG内核通过pg_hba.conf完成客户端认证(2)...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

Python Ovito统计金刚石结构数量

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

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...