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

开源bert-base-chinese应用:中文社交媒体谣言检测的语义表征建模

开源bert-base-chinese应用&#xff1a;中文社交媒体谣言检测的语义表征建模 1. 引言&#xff1a;当谣言遇上AI 你有没有在社交媒体上刷到过一些真假难辨的消息&#xff1f;比如“某地出现不明病毒”、“某食品含有致癌物”&#xff0c;这些信息往往传播迅速&#xff0c;让人…...

4个步骤掌握高频交易策略:High-Frequency-Trading-Model-with-IB实战指南

4个步骤掌握高频交易策略&#xff1a;High-Frequency-Trading-Model-with-IB实战指南 【免费下载链接】High-Frequency-Trading-Model-with-IB A high-frequency trading model using Interactive Brokers API with pairs and mean-reversion in Python 项目地址: https://gi…...

ClawdBot实战教程:零基础搭建个人AI助手的完整流程

ClawdBot实战教程&#xff1a;零基础搭建个人AI助手的完整流程 1. ClawdBot简介&#xff1a;你的本地AI助手 ClawdBot是一个可以在个人设备上运行的AI助手解决方案&#xff0c;基于vLLM提供后端模型能力。与常见的云端AI服务不同&#xff0c;它完全运行在本地环境中&#xff…...

网络工程师-核心考点:计算机硬件基础全解析

一、引言计算机硬件基础是软考网络工程师考试的前置知识点&#xff0c;占选择题分值约 3-5 分&#xff0c;是理解网络设备&#xff08;路由器、交换机、服务器&#xff09;硬件架构的底层基础。本知识点体系起源于 1945 年冯・诺依曼提出的存储程序思想&#xff0c;历经 70 余年…...

ai辅助开发:让快马生成智能助手,链接notepad下载与个性化代码推荐

今天想和大家分享一个有趣的实践&#xff1a;如何用AI辅助开发的方式&#xff0c;让Notepad这个老牌文本编辑器焕发新生。我们平时下载Notepad可能只是简单获取软件&#xff0c;但如果结合AI能力&#xff0c;就能把"下载-使用"的流程升级成"智能助手"体验。…...

别再只看灰度图了!用功率谱给你的AI生成图像质量把把脉

功率谱分析&#xff1a;AI生成图像质量评估的隐藏利器 当我们在评估AI生成的图像时&#xff0c;常常会陷入主观判断的陷阱——肉眼观察虽然直观&#xff0c;但缺乏量化标准。而功率谱分析这一源自信号处理的技术&#xff0c;正悄然成为AI图像质量评估领域的一把精准尺子。不同于…...

VSCode配置STM32标准库开发环境:手把手解决core_cm3.c编译报错与头文件路径问题

VSCode搭建STM32开发环境&#xff1a;解决标准库兼容性与智能感知难题 当开发者从Keil或IAR转向VSCode时&#xff0c;往往会遇到两个棘手的拦路虎&#xff1a;标准库与GCC的兼容性问题&#xff0c;以及代码智能感知的缺失。本文将深入解决这两个核心痛点&#xff0c;带你构建一…...

OpenClaw自动化周报生成:Qwen3-32B私有镜像精准提取Git提交记录

OpenClaw自动化周报生成&#xff1a;Qwen3-32B私有镜像精准提取Git提交记录 1. 为什么需要自动化周报生成 每周五下午&#xff0c;我都会面临同样的困扰&#xff1a;需要从零散的Git提交记录中手动整理本周工作内容&#xff0c;再拼凑成一份结构化的周报。这个过程不仅耗时&a…...

谈谈你对springAop动态代理的理解?

面试 你要调用目标方法&#xff0c;不直接调用&#xff0c;而是交给代理对象&#xff0c;代理对象会先做额外功能&#xff0c;再调用原方法&#xff0c;最后再收尾。 至于叫动态代理的原因&#xff0c;是因为这个代理不是你手动写死的&#xff0c;而是程序在运行期间动态生成…...

PySide6商业项目避坑指南:从许可证验证到Qt Designer实战

PySide6商业项目避坑指南&#xff1a;从许可证合规到UI开发实战 当企业开发者选择PySide6作为桌面应用开发框架时&#xff0c;往往会被其商业友好的LGPL许可证所吸引。但真正落地到项目开发中&#xff0c;从法律合规到技术实现都存在诸多需要特别注意的细节。本文将深入剖析那些…...