【算法】递归型枚举与回溯剪枝初识

news2025/3/6 11:24:19

递归型枚举与回溯剪枝初识

  • 1.枚举子集
  • 2.组合型枚举
  • 3.枚举排列
  • 4.全排列问题

  1. 什么是搜索?搜索,是一种枚举,通过穷举所有的情况来找到最优解,或者统计合法解的个数。因此,搜索有时候也叫作暴搜。搜索一般分为深度优先搜索(DFS)与宽度优先搜索(BFS)。
  2. 深度优先遍历 vs 深度优先搜索,宽度优先遍历 vs 宽度优先搜索。遍历是形式,搜索是目的。不过,在一般情况下,我们不会去纠结概念的差异,两者可以等同。
  3. 回溯与剪枝
  • 回溯:当在搜索的过程中,遇到走不通或者走到底的情况时,就回头。
  • 剪枝:在搜索过程中,剪掉重复出现或者不是最优解的分。

递归型枚举与回溯剪枝初识:

  • 画决策树
  • 根据决策树写递归

搜索的本质:对决策树进行一次遍历,直到将所有的情况搜集到为止。

1.枚举子集

B3622 枚举子集(递归实现指数型枚举)

在这里插入图片描述

解法:深搜

设一共有 3 人,分别是 1,2,3。「从前往后」考虑每一个人,针对当前这个人「选」或者「不选」,我们可以画出如下「决策树」:

在这里插入图片描述

设计递归函数:

  1. 重复子问题:针对某一位,「选」或者「不选」。因为最终结果要按照「字典序」输出,我们可以「先考虑不选」,然后「再考虑选」。
  2. 实现方式参考代码和注释,结合「决策树」一起看会很清晰。
#include<iostream>
#include<string>
using namespace std;

const int N = 11;

int n;
string path; //记录递归过程中,每⼀步的决策

void dfs()
{
    if(path.size() == n)
    {
        cout << path << endl; //path存着前n个⼈的决策 
        return;
    }
    
    //不选
    path += 'N';
    dfs();
    path.pop_back(); //回溯:恢复现场
    
    //选
    path += 'Y';
    dfs(); 
    path.pop_back(); //回溯:恢复现场
}

int main()
{
    cin >> n;
    dfs();
    
    return 0;
}

2.组合型枚举

P10448 组合型枚举

在这里插入图片描述

解法:深搜

设 n = 4, m = 3,「从前往后」考虑 3 个位置应该选哪个数,我们可以画出如下决策树:

在这里插入图片描述

设计递归函数:

  1. 重复子问题:当前这一位,应该放哪个数上去。因为这是一个「组合」问题,不涉及排列,所以我们当前位置开始放的数,应该是「上次决策的数的下一位」。
  2. 实现方式参考代码和注释,结合「决策树」一起看会很清晰。
#include<iostream>
#include<vector>
using namespace std;

int n, m;
vector<int> path; //记录递归过程中,每⼀步的决策

void dfs(int pos)
{
    if(path.size() == m)
    {
        for(auto& e : path) cout << e << " ";
        cout << endl;
        return;
    }
    
    for(int i = pos; i <= n; i++)
    {
        path.push_back(i);
        dfs(i + 1);
        path.pop_back(); //回溯:恢复现场
    }
}

int main()
{
    cin >> n >> m;
    dfs(1);
    
    return 0;
}

3.枚举排列

B3623 枚举排列(递归实现排列型枚举)

在这里插入图片描述

解法:深搜

设 n = 3, k = 2,一共要选出两个数,可以依次「考虑要选出来的数」是谁,画出如下决策树:

在这里插入图片描述

设计递归函数:

  1. 重复子问题:考虑这一位要放上什么数。因为是「排列」问题,所以我们直接从 1 开始枚举要放的数。
  2. 剪枝:在这一条路径中,我们「不能选择之前已经选择过的数」,需要用到辅助数组
  3. 实现方式参考代码和注释,结合「决策树」一起看会很清晰。
#include<iostream>
#include<vector>
using namespace std;

const int N = 15;

int n, k;
vector<int> path; //记录递归过程中,每⼀步的决策
bool vis[N]; //辅助数组:标记哪些数已经选过 

void dfs()
{
    if(path.size() == k)
    {
        for(auto& e : path) cout << e << " ";
        cout << endl;
        return;
    }
    
    for(int i = 1; i <= n; i++)
    {
        if(vis[i] == false)
        {
            vis[i] = true;
            path.push_back(i);
            dfs();
            
            //回溯:恢复现场
            path.pop_back();
            vis[i] = false;
        }
    }
}

int main()
{
    cin >> n >> k;
    dfs();
    
    return 0;
}

4.全排列问题

P1706 全排列问题

在这里插入图片描述

解法:深搜

跟上一道题的决策一样,我们可以枚举每一位应该放上什么数,只不过少了 k 的限制。剪枝的策略还是一样的,那就是在路径中,「不能选择之前已经选过的数」。

在这里插入图片描述

#include<iostream>
#include<vector>
using namespace std;

const int N = 15;

int n;
vector<int> path; //记录递归过程中,每⼀步的决策
bool vis[N]; //辅助数组:标记哪些数已经选过

void dfs()
{
    if(path.size() == n)
    {
        for(auto& e : path) printf("%5d", e);
        cout << endl;
        return;
    }
    
    for(int i = 1; i <= n; i++)
    {
        if(vis[i] == false)
        {
            vis[i] = true;
            path.push_back(i);
            dfs();
            
            //回溯:恢复现场
            path.pop_back();
            vis[i] = false;
        }
    }
}

int main()
{
    cin >> n;
    dfs();
    
    return 0;
}

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

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

相关文章

rocketmq-product-send方法源码分析

先看有哪些send方法 首先说红圈的 有3个红圈。归类成3种发送方式。假设前提条件&#xff0c;发送的topic&#xff0c;有3个broker&#xff0c;每个broker总共4个write队列&#xff0c;总共有12个队列。 普通发送。负载均衡12个队列。指定超时时间指定MessageQueue,发送&#…

69.在 Vue 3 中使用 OpenLayers 拖拽实现放大区域的效果(DragPan)

引言 在现代 Web 开发中&#xff0c;地图功能已经成为许多应用的重要组成部分。OpenLayers 是一个功能强大的开源地图库&#xff0c;支持多种地图源和交互操作。Vue 3 是一个流行的前端框架&#xff0c;以其响应式数据和组件化开发著称。本文将介绍如何在 Vue 3 中集成 OpenLa…

77,【1】.[CISCN2019 华东南赛区]Web4

有句英文&#xff0c;看看什么意思 好像也可以不看 进入靶场 点击蓝色字体 我勒个豆&#xff0c;百度哇 所以重点应该在url上&#xff0c;属于任意文件读取类型 接下来该判断框架了 常见的web框架如下 一&#xff0c;Python 框架 1.Flask URL 示例 1&#xff1a;http://…

手撕B-树

一、概述 1.历史 B树&#xff08;B-Tree&#xff09;结构是一种高效存储和查询数据的方法&#xff0c;它的历史可以追溯到1970年代早期。B树的发明人Rudolf Bayer和Edward M. McCreight分别发表了一篇论文介绍了B树。这篇论文是1972年发表于《ACM Transactions on Database S…

一文简单回顾复习Java基础概念

还是和往常一样&#xff0c;我以提问的方式回顾复习&#xff0c;今天回顾下Java小白入门应该知道的一些基础知识 Java语言有哪些特点呢&#xff1f; Java语言的特点有&#xff1a; 面向对象&#xff0c;主要是封装、继承、多态&#xff1b;平台无关性&#xff0c;“一次编写…

GCC之编译(8)AR打包命令

GCC之(8)AR二进制打包命令 Author: Once Day Date: 2025年1月23日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章请查看专栏: Linux实践记录_Once-Day的博客-C…

2.1.3 第一个工程,点灯!

新建工程 点击菜单栏左上角&#xff0c;新建工程或者选择“文件”-“新建工程”&#xff0c;选择工程类型“标准工程”选择设备类型和编程语言&#xff0c;并指定工程文件名及保存路径&#xff0c;如下图所示&#xff1a; 选择工程类型为“标准工程” 选择主模块机型&#x…

图像处理算法研究的程序框架

目录 1 程序框架简介 2 C#图像读取、显示、保存模块 3 C动态库图像算法模块 4 C#调用C动态库 5 演示Demo 5.1 开发环境 5.2 功能介绍 5.3 下载地址 参考 1 程序框架简介 一个图像处理算法研究的常用程序逻辑框架&#xff0c;如下图所示 在该框架中&#xff0c;将图像处…

计算机工程:解锁未来科技之门!

计算机工程与应用是一个充满无限可能性的领域。随着科技的迅猛发展&#xff0c;计算机技术已经深深渗透到我们生活的方方面面&#xff0c;从医疗、金融到教育&#xff0c;无一不在彰显着计算机工程的巨大魅力和潜力。 在医疗行业&#xff0c;计算机技术的应用尤为突出。比如&a…

Linux初识——基本指令(2)

本文将继续从上篇末尾讲起&#xff0c;讲解我们剩下的基本指令 一、剩余的基本指令 1、mv mv指令是move&#xff08;移动&#xff09;的缩写&#xff0c;其功能为&#xff1a;1.剪切文件、目录。2.重命名 先演示下重命名&#xff0c;假设我想把当前目录下的di34改成dir5 那…

单片机-STM32 WIFI模块--ESP8266 (十二)

1.WIFI模块--ESP8266 名字由来&#xff1a; Wi-Fi这个术语被人们普遍误以为是指无线保真&#xff08;Wireless Fidelity&#xff09;&#xff0c;并且即便是Wi-Fi联盟本身也经常在新闻稿和文件中使用“Wireless Fidelity”这个词&#xff0c;Wi-Fi还出现在ITAA的一个论文中。…

80,【4】BUUCTF WEB [SUCTF 2018]MultiSQL

53&#xff0c;【3】BUUCTF WEB october 2019 Twice SQLinjection-CSDN博客 上面这个链接是我第一次接触二次注入 这道题也涉及了 对二次注入不熟悉的可以看看 BUUCTF出了点问题&#xff0c;打不开&#xff0c;以下面这两篇wp作为学习对象 [SUCTF 2018]MultiSQL-CSDN博客 …

Prometheus部署及linux、mysql、monog、redis、RocketMQ、java_jvm监控配置

Prometheus部署及linux、mysql、monog、redis、RocketMQ、java_jvm监控配置 1.Prometheus部署1.2.Prometheus修改默认端口 2.grafana可视化页面部署3.alertmanager部署4.监控配置4.1.主机监控node-exporter4.2.监控mysql数据库mysqld_exporter4.3.监控mongod数据库mongodb_expo…

问题排查 - TC397 CORE2 50MS/100MS任务不运行

1、问题描述 CORE2 的任务运行次数的计数值OsTask_100ms_Core2 - task_cnt[12]、OsTask_50ms_Core2 - task_cnt[16]不在累加&#xff0c;但是其他任务OsAlarm_1ms_Core2、OsAlarm_5ms_Core2、OsAlarm_10ms_Core2、OsAlarm_20ms_Core2 任务计数值累加正常。 如果是任务栈溢出&a…

Spring FatJar写文件到RCE分析

背景 现在生产环境部署 spring boot 项目一般都是将其打包成一个 FatJar&#xff0c;即把所有依赖的第三方 jar 也打包进自身的 app.jar 中&#xff0c;最后以 java -jar app.jar 形式来运行整个项目。 运行时项目的 classpath 包括 app.jar 中的 BOOT-INF/classes 目录和 BO…

百度APP iOS端磁盘优化实践(上)

01 概览 在APP的开发中&#xff0c;磁盘管理已成为不可忽视的部分。随着功能的复杂化和数据量的快速增长&#xff0c;如何高效管理磁盘空间直接关系到用户体验和APP性能。本文将结合磁盘管理的实践经验&#xff0c;详细介绍iOS沙盒环境下的文件存储规范&#xff0c;探讨业务缓…

蓝桥杯之c++入门(一)【第一个c++程序】

目录 前言一、第⼀个C程序1.1 基础程序1.2 main函数1.3 字符串1.4 头文件1.5 cin 和 cout 初识1.6 名字空间1.7 注释 二、四道简单习题&#xff08;点击跳转链接&#xff09;练习1&#xff1a;Hello,World!练习2&#xff1a;打印飞机练习3&#xff1a;第⼆个整数练习4&#xff…

14-6-1C++STL的list

(一&#xff09;list容器的基本概念 list容器简介&#xff1a; 1.list是一个双向链表容器&#xff0c;可高效地进行插入删除元素 2.list不可以随机存取元素&#xff0c;所以不支持at.(pos)函数与[ ]操作符 &#xff08;二&#xff09;list容器头部和尾部的操作 list对象的默…

【AI论文】Sigma:对查询、键和值进行差分缩放,以实现高效语言模型

摘要&#xff1a;我们推出了Sigma&#xff0c;这是一个专为系统领域设计的高效大型语言模型&#xff0c;其独特之处在于采用了包括DiffQKV注意力机制在内的新型架构&#xff0c;并在我们精心收集的系统领域数据上进行了预训练。DiffQKV注意力机制通过根据查询&#xff08;Q&…

InceptionV1_V2

目录 不同大小的感受野去提取特征 经典 Inception 网络的设计思路与运行流程 背景任务&#xff1a;图像分类&#xff08;以 CIFAR-10 数据集为例&#xff09; Inception 网络的设计思路 Inception 网络的运行流程 打个比方 多个损失函数的理解 1. 为什么需要多个损失函数&#…