从0开始的算法(数据结构和算法)基础(十一)

news2024/11/14 23:27:06

回溯算法

什么是回溯算法

   回溯算法,根据字面意思来理解这个算法是将每一步的操作可以进行回溯,实际上是对这个每一步的操作进行记录,确保可以返回上一步的操作,可能是对回溯操作之前的做一个复现,也有可能是可操作的回退,这个观点是错误的通过尝试不同的选择并记录当前状态,当遇到不符合要求的解时,能够回溯到之前的状态进行新的尝试,备份回退。 特别适用于解决组合、排列、子集等问题。其核心思想是在搜索过程中,我也不知道为什么,因为在我的理解里面觉得,只要能够回到当前的状态,重新做一个复现,也是可以的只不过耗费时间和空间,一个更大型的穷举,而且可以确定问题出现的多个地方的可能性。

leetcode经典问题

为了解释回溯算法的实际应用流程,我将提供一个简单的回溯算法流程图,以及一个使用 Java 实现的回溯算法示例。以下是解决N 皇后问题的回溯算法流程图及其 Java 代码。

回溯算法流程图

开始
初始化变量
调用递归函数
是否所有皇后都已放置?
记录解
结束
在当前行的每一列尝试放置皇后
放置是否合法?
继续递归到下一行
尝试下一个列

流程图说明

  1. 开始: 算法启动。
  2. 初始化变量: 设置棋盘大小和用于存放皇后位置的数组。
  3. 调用递归函数: 从第一行开始尝试放置皇后。
  4. 是否所有皇后都已放置?: 检查当前行是否已放置所有皇后。
    • : 记录当前解,并结束算法。
    • : 继续尝试在当前行放置皇后。
  5. 在当前行的每一列尝试放置皇后: 遍历当前行的所有列。
  6. 放置是否合法?: 检查当前放置的皇后是否冲突。
    • : 继续递归到下一行。
    • : 尝试在当前行的下一个列放置皇后。

您可以将上述 Mermaid 代码粘贴到支持 Mermaid 的工具或编辑器中(如 Markdown 编辑器、Mermaid Live Editor 等),来查看生成的流程图。希望这能帮助您理解回溯算法的流程!

Java 实现代码:N 皇后问题

以下是一个回溯算法在 Java 中解决 N 皇后问题的示例:

import java.util.ArrayList;
import java.util.List;

public class NQueens {

    public static void main(String[] args) {
        int n = 4; // 可以改变n的值,来测试不同的棋盘大小
        List<List<String>> solutions = solveNQueens(n);
        for (List<String> solution : solutions) {
            for (String row : solution) {
                System.out.println(row);
            }
            System.out.println();
        }
    }

    public static List<List<String>> solveNQueens(int n) {
        List<List<String>> result = new ArrayList<>();
        int[] queens = new int[n];
        solve(0, n, queens, result);
        return result;
    }

    private static void solve(int row, int n, int[] queens, List<List<String>> result) {
        if (row == n) {
            result.add(generateBoard(queens, n));
            return;
        }
        for (int col = 0; col < n; col++) {
            if (isValid(queens, row, col)) {
                queens[row] = col;
                solve(row + 1, n, queens, result);
                queens[row] = -1;  // 回溯
            }
        }
    }

    private static boolean isValid(int[] queens, int row, int col) {
        for (int i = 0; i < row; i++) {
            if (queens[i] == col || Math.abs(queens[i] - col) == Math.abs(i - row)) {
                return false;
            }
        }
        return true;
    }

    private static List<String> generateBoard(int[] queens, int n) {
        List<String> board = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            char[] row = new char[n];
            for (int j = 0; j < n; j++) {
                row[j] = (queens[i] == j) ? 'Q' : '.';
            }
            board.add(new String(row));
        }
        return board;
    }
}

代码解读

  1. solveNQueens 方法:初始化棋盘,并调用 solve 方法开始递归。

  2. solve 方法:这个方法使用递归来尝试在每一行放置皇后,并检查当前位置是否安全。如果皇后可以安全放置,则继续递归地解决下一行的问题;如果没有合法的位置,则回溯到前一个状态。

  3. isValid 方法:检查当前放置皇后的状态是否合法,即是否与前面已经放置的皇后发生冲突。

  4. generateBoard 方法:当找到一个解时,生成该解对应的棋盘表示,并将其加入到结果集中。

回溯算法实际应用场景

回溯算法被广泛应用于以下场景:

  • 组合问题:比如组合、排列、子集问题。
  • 图问题:如迷宫问题、图着色问题。
  • 搜索问题:如数独、八皇后问题等。
  • 排列和优化问题:如旅行商问题、背包问题等。

实际生活中的应用

回溯算法在解决组合、排列、约束满足问题等复杂问题时非常有效,它不仅用于计算机科学和数学中,还在实际生活中有广泛的应用。以下是一些回溯算法在实际生活中的应用场景:

1. 旅行路线规划
  • 应用场景:旅行者需要规划一条从起点到终点经过多个城市的路线,并且可能有时间、距离等限制。
  • 回溯算法的作用:回溯算法可以尝试不同的路线组合,评估每一条路线是否满足约束条件(如最短距离或最低花费)。如果某条路线不符合要求,则回退并重新尝试其他路线,最终找到最优解。

滴滴司机顺风车的固定路线的产生
在这里插入图片描述

2. 课程安排与考试安排
  • 应用场景:学校或大学的课程安排或考试安排,必须考虑到多个约束条件(如教师的时间、教室的数量、学生的选课冲突等)。
  • 回溯算法的作用:回溯算法通过尝试不同的安排方式,逐步构建课程或考试安排表,并在发现安排冲突时,回溯到前一步重新安排。它可以帮助生成一份符合所有约束条件的合理排课表或考试表。
    在这里插入图片描述
3. 自然语言处理中的解析问题
  • 应用场景:在自然语言处理(NLP)任务中,解析句子结构时需要考虑语法规则,找到一种符合语法的解析方式。
  • 回溯算法的作用:当某一解析方式不符合语法时,算法可以回溯,尝试其他解析路径。这在语法分析器中常用。
4. 组合优化问题
  • 应用场景:比如商店打折活动中,商家可能要从多个促销组合中选出满足某种条件的最佳方案,如最少成本或者最大收益。
  • 回溯算法的作用:可以通过尝试每种促销组合,当某种组合不满足条件时,回退到前一组并尝试其他促销方案,从而找到最优解。
5. 人力资源的任务分配
  • 应用场景:公司在管理任务分配时,要将任务分配给员工,同时满足员工的时间、技能等多种约束。
  • 回溯算法的作用:尝试为每个任务分配合适的员工,如果某个任务分配不合理,则回退,重新进行分配,最终找到满足所有约束条件的分配方式。

6. DNA测序问题

  • 应用场景:生物信息学中的DNA序列比对,找到最适合的DNA片段拼接方式。
  • 回溯算法的作用:通过尝试不同片段的组合,逐步拼接DNA片段,并在拼接不匹配时回退到之前的步骤,直到找到最合适的拼接方案。

在这里插入图片描述
给个关注呗,持续更新中~~持续输出内容

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32与ESP8266的使用

串口透传 “透传”通常指的是数据的透明传输&#xff0c;意思是在不对数据进行任何处理或修改的情况下&#xff0c;将数据从一个接口转发到另一个接口。值得注意的是要避免串口之间无限制的透明&#xff0c;可以采用互斥锁的方式进行限制使用方法 对USART1和USART3(用他俩举例…

高效物流管理从固乔快递批量查询助手开始

固乔快递批量查询助手&#xff1a;物流管理的智能化升级 固乔快递查询助手&#xff1a;批量追踪&#xff0c;物流无忧 轻松应对海量单号&#xff0c;固乔快递批量查询助手来帮忙 跨境电商新利器&#xff1a;固乔快递批量查询助手 高效物流管理从固乔快递批量查询助手开始 …

Spring-AOP核心源码、原理详解前篇

本文主要分4部分 Aop原理介绍介绍aop相关的一些类通过源码详解aop代理的创建过程通过源码详解aop代理的调用过程Aop代理一些特性的使用案例 Spring AOP原理 原理比较简单&#xff0c;主要就是使用jdk动态代理和cglib代理来创建代理对象&#xff0c;通过代理对象来访问目标对象…

漏洞复现-泛微-E-Cology-SQL

更多漏洞分析复现&#xff0c;可前往无问社区查看http://www.wwlib.cn/index.php/artread/artid/10358.html 0x01 产品简介 泛微e-cology是一款由泛微网络科技开发的协同管理平台&#xff0c;支持人力资源、财务、行政等多功能管理和移动办公。 0x02 漏洞概述 泛微e-cology…

路由器WAN口和LAN口有什么不一样?

“ 路由器WAN口和LAN口的区别&#xff0c;WAN是广域网端口&#xff0c;LAN是本地网端口。WAN主要用于连接外部网络&#xff0c;而LAN用来连接家庭内部网络&#xff0c;两者主要会在标识上面有区别。以往大部分路由器的WAN只有一个&#xff0c;LAN口则有四个或以上&#xff0c;近…

shader 案例学习笔记之偏移

效果 代码 #ifdef GL_ES precision mediump float; #endifuniform vec2 u_resolution; uniform float u_time;vec2 brickTile(vec2 _st, float _zoom){_st * 5.;_st.x step(1., mod(_st.y,2.0)) * 0.5;return fract(_st); }float box(vec2 _st, vec2 _size){_size vec2(0.5)…

红帽9中nginx-源码编译php

什么是PHP-FPM&#xff1f; PHP-FPM(FastCGI Process Manager&#xff1a; FastCGI进程管理器)是一个实现了Fastcgi的程序&#xff0c;并且提供进程管理的功能。 进程包括master进程和worker进程。master进程只有一个&#xff0c;负责监听端口&#xff0c;接受来自web server 的…

Linux进程(2)(进程状态 - 僵尸、孤儿进程)

目录 1.进程状态 1&#xff09;直接谈论Linux的进程状态 R &#xff1a;进程运行的状态 S &#xff1a;休眠状态 &#xff08;进程在等待“资源”就绪&#xff1b;可中断睡眠&#xff09; T / t &#xff1a;让进程暂停&#xff0c;等待被进一步唤醒 D …

【springboot】整合spring security 和 JWT

目录 1. 整合spring security 1. 导入依赖 2. 配置类 3. 实体类实现UserDetails接口 4. 业务逻辑实现类实现UserDetailsService接口 5. 控制类实现登录功能 6. 测试登录功能 2. 分析源码 1. UsernamePasswordAuthenticationToken 2. A…

【c/c++】类型转换:隐式类型转换、强制类型转换

目录 前言 一、了解类型转换 二、隐式类型转换 1.适用场景 2.转换规则 三、强制类型转换 适用场景 使用规则 注意事项 前言 类型转换是编程中一个常见的现象。在我们进行编码的时候不经意间就发生了&#xff0c;但却能让整个程序运行得更加流畅。 但是这种不经意&am…

C++:STL之vector

1.vector的使用 1.1vector的定义 使用vector需要包含头文件 #include<vector> vector的构造 &#xff08;constructor&#xff09;构造函数声明接口说明vector() (重点)无参构造vector(size_type n,const value_type& val value_type())用n个val初始化并构造vecto…

Java11环境安装(Windows)

目录 1 Java11安装2 配置2.1 JavaHome配置2.2 CLASSPATH配置PATH路径配置 3 验证 1 Java11安装 从官网下载Java11安装包&#xff1a;jdk-11_windows-x64_bin.exe,安装时选择安装到D:\Java目录。 安装完目录结构如下&#xff1a; 2 配置 2.1 JavaHome配置 如下图所示配置JAV…

Ubuntu构建只读文件系统

本文介绍Ubuntu构建只读文件系统。 嵌入式系统使用过程中&#xff0c;有时会涉及到非法关机&#xff08;比如直接关机&#xff0c;或意外断电&#xff09;&#xff0c;这可能造成文件系统损坏&#xff0c;为了提高系统的可靠性&#xff0c;通常将根文件系统设置为只读&#xf…

Linux下进程间的通信--信号量

前言&#xff1a; 资源竞争&#xff1a; 资源竞争&#xff08;Race Condition&#xff09;是多线程或多进程环境中的一种常见问题&#xff0c;它发生在多个进程或线程并发访问和修改同一资源&#xff08;如内存位置、文件、数据库记录等&#xff09;时&#xff0c;而最终结果…

mysql学习教程,从入门到精通,SQL AND OR 运算符(12)

1、SQL AND & OR 运算符 在本教程中&#xff0c;您将学习如何在子句中使用ASELECT column1_name, column2_name, columnN_nameFROM table_nameWHERE condition1 AND condition2;ND&#xff06;OR运算符&#xff0c;WHERE以根据多个条件过滤记录。 1.1、根据条件选择记录 …

从代码直观理解Self-Attention和Cross-Attention的本质区别

Transformer的模型架构实际上非常简单&#xff0c;Self-Attention 和 Cross-Attention 仅仅是在 k, v上有所不同&#xff08;这里不讨论 mask&#xff09;。 论文原文&#xff1a;Attention Is All You Need 我们可以使用同一个 Attention 类来实现 Self-Attention 和 Cross-At…

day11-多线程

一、线程安全问题 线程安全问题出现的原因&#xff1f;存在多个线程在同时执行同时访问一个共享资源存在修改该共享资源 线程安全:多个线程同时修改同一个资源 取钱案例 小明和小红是一对夫妻&#xff0c;他们有一个共同的账户&#xff0c;余额是10万元 如果小明和小红同时来取…

速看!6款可以写论文的ai写作网站,这才是真正的论文神器!(含教程)

在当今信息爆炸的时代&#xff0c;AI写作工具的出现极大地提高了写作效率和质量。特别是对于需要撰写论文的学生和研究人员来说&#xff0c;这些工具提供了极大的便利。本文将重点介绍一款备受推荐的AI写作平台——千笔-AIPassPaper&#xff0c;并结合相关教程帮助用户更好地使…

【北京迅为】《STM32MP157开发板使用手册》- 第二十四章 STM32CubeIDE的初步使用

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

校园水电费管理微信小程序的设计与实现+ssm(lw+演示+源码+运行)

校园水电费管理小程序 摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来…