当前位置: 首页 > 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)...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...