DFS之剪枝与优化——AcWing 165. 小猫爬山

DFS之剪枝与优化

定义

DFS之剪枝与优化指的是在执行深度优先搜索(DFS, Depth-First Search)时,采取的一系列策略来减少搜索空间,避免无效计算,从而加速找到问题的解。剪枝是指在搜索过程中,当遇到某些条件不符合解的要求或者可以预判后续搜索不会产生有效解时,直接放弃这条搜索路径,这一过程称为剪枝。优化则是指通过调整搜索策略、顺序等,提高搜索效率。

运用情况

  1. 组合优化问题:如全排列、组合总和、子集问题等,剪枝可以避免生成无效解。
  2. 图的遍历与搜索:在寻找特定路径或计算连通分量时,剪枝可以减少搜索范围。
  3. 游戏AI:如棋类游戏中预测对手可能的走法,剪枝减少计算量。
  4. 约束满足问题:如数独、任务调度等,剪枝帮助快速排除不满足条件的解。

注意事项

  1. 剪枝条件的选择:剪枝条件应严格且准确,避免误剪有效解。
  2. 搜索顺序:合理安排搜索顺序,优先探索最有希望的分支。
  3. 状态重置:回溯时确保正确恢复现场,避免状态污染。
  4. 记忆化:对于重复子问题,使用记忆化技术存储中间结果,避免重复计算。
  5. 资源管理:注意栈或递归深度限制,防止栈溢出。

解题思路

  1. 明确剪枝条件:分析问题特性,确定何时可以安全地剪枝。
  2. 优化搜索顺序
    • 分支较少优先:优先探索分支较少的路径,减少搜索深度。
    • 启发式排序:依据某种评估函数排序待探索节点,优先探索最有潜力的节点。
  3. 可行性剪枝:在探索前,如果可以证明当前路径无法导致有效解,立即剪枝。
  4. 最优性剪枝:在某些最优化问题中,如果已知当前路径不能优于已找到的最佳解,剪枝。
  5. 迭代加深DFS:结合深度限制,逐步增加深度限制进行搜索,适用于寻找最短路径等问题。
  6. 记忆化搜索:在适用场景下,利用动态规划思想存储中间结果,避免重复计算。

AcWing 165. 小猫爬山

题目描述

165. 小猫爬山 - AcWing题库

运行代码

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20;

int n, m;
int w[N];
int sum[N];
int ans = N;

void dfs(int u, int k)
{
    if(k >= ans) return;
    if(u == n)
    {
        ans = k;
        return;
    }
    for(int i = 0; i < k; i ++ )
        if(sum[i] + w[u] <= m)
        {
            sum[i] += w[u];
            dfs(u + 1, k);
            sum[i] -= w[u];
        }
    sum[k] = w[u];
    dfs(u + 1, k + 1);
    sum[k] = 0;
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++ ) cin >> w[i];
    sort(w, w + n, greater<int>());
    dfs(0, 0);
    cout << ans << endl;
    return 0;
}

代码思路

  1. 输入与初始化:读取小猫数量 n 和缆车最大承重 m,以及每只小猫的重量 w[],并按重量从大到小排序。
  2. DFS搜索:定义一个深度优先搜索函数 dfs(u, k),其中 u 是当前考虑的小猫索引,k 是当前已经考虑过的缆车数量。
    • 当搜索到的缆车数量 k 大于或等于已知的最小缆车数量 ans 时,提前结束此分支的搜索。
    • 当所有小猫都被考虑过后,更新最小缆车数量 ans
    • 对于每辆缆车,尝试将当前小猫放入(如果总重不超过 m),递归搜索下一个位置的小猫。递归结束后回溯,撤销选择。
  3. 主函数逻辑:初始化数组 sum[] 用于记录每辆缆车的当前载重,然后调用 dfs() 函数,最后输出最小缆车数量 ans

其它代码

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20;

int n, m;
int w[N];
int sum[N];
int ans = N;

void dfs(int u, int k)
{
    if(k >= ans) return;
    if(u == n)
    {
        ans = k;
        return;
    }
    for(int i = 0; i < k; i ++ )
        if(sum[i] + w[u] <= m)
        {
            sum[i] += w[u];
            dfs(u + 1, k);
            sum[i] -= w[u];
        }
    sum[k] = w[u];
    dfs(u + 1, k + 1);
    sum[k] = 0;
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++ ) cin >> w[i];
    //sort(w, w + n, greater<int>());
    dfs(0, 0);
    cout << ans << endl;
    return 0;
}

代码思路

  1. 变量定义:

    • n: 表示小猫的数量。
    • m: 表示每辆缆车的最大承重。
    • w[N]: 存储每只小猫的重量。
    • sum[N]: 记录每辆缆车当前的总重量。
    • ans: 初始设置为一个较大的数(N),用于记录最少需要的缆车数量,最终会被更新为实际的最小数量。
  2. 主函数逻辑:

    • 读取小猫数量 n 和缆车最大承重 m
    • 输入每只小猫的重量 w[]。注意代码中去掉了原先对w[]进行排序的部分,这在原始代码中是为了优化搜索过程,因为通常按照重量从大到小处理可以更快达到最优解,但这里为了保持原始逻辑解释,未进行排序。
    • 调用深度优先搜索函数 dfs(u, k) 进行求解,其中 u 表示当前考虑的小猫索引(从0开始),k 表示当前已经分配的缆车数量。
    • 输出最少缆车数量 ans
  3. 深度优先搜索 (DFS) 函数逻辑:

    • 剪枝条件: 当已分配的缆车数量 k 大于等于已知的最小缆车数量 ans 时,直接返回,因为后续的搜索不会得到更好的解。
    • 终止条件: 当所有小猫都被考虑过(即 u == n)时,更新 ans 为当前的缆车数量 k,然后返回。
    • 尝试分配小猫到已有缆车:
      • 遍历之前的所有缆车(用 i 表示),检查当前小猫是否能加入到缆车 i 中(即 sum[i] + w[u] <= m)。
        • 如果可以加入,就临时增加 sum[i] 的值,然后递归调用 dfs 函数尝试分配下一个猫,分配完后再恢复 sum[i] 的值(回溯)。
    • 尝试分配到新缆车:
      • 将当前小猫分配到一个新的缆车(即 sum[k] = w[u]),然后递归调用 dfs 函数分配下一个猫,分配完后清空 sum[k](因为这是尝试过程中的状态,不是最终分配)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Day05-02-Jenkins-pipeline

Day05-02-Jenkins-pipeline 1. Jenkins-Pipeline概述1) pipeline? 2. pipeline格式3. 小试牛刀4. Java上线的项目4.1 流程汇总4.2 根据流程书写pipeline架构4.3 分步实现1&#xff09;拉取代码2&#xff09;检查,编译,部署 4.4 完整pipeline代码 5. 根据tag标签拉取代码(了解自…

FreeBSD@ThinkPad x250因电池耗尽关机后无法启动的问题存档

好几次碰到电池耗尽FreeBSD关机&#xff0c;再启动&#xff0c;网络通了之后到了该出Xwindows窗体的时候&#xff0c;屏幕灭掉&#xff0c;网络不通&#xff0c;只有风扇在响&#xff0c;启动失败。关键是长按开关键后再次开机&#xff0c;还是启动失败。 偶尔有时候重启到单人…

温州网站建设方案及报价

随着互联网的发展&#xff0c;网站建设已经成为企业推广和营销的重要手段。温州作为中国经济发达地区之一&#xff0c;各行各业企业纷纷意识到网站建设的重要性&#xff0c;纷纷加大网站建设工作的投入。那么&#xff0c;温州网站建设方案及报价是怎样的呢&#xff1f;下面我们…

深入理解C# log4Net日志框架:功能、使用方法与性能优势

文章目录 1、log4Net的主要特性2、log4Net框架详解配置日志级别 3、log4Net的使用示例4、性能优化与对比5、总结与展望 在软件开发过程中&#xff0c;日志记录是一个不可或缺的功能。它可以帮助开发者追踪错误、监控应用程序性能&#xff0c;以及进行调试。在C#生态系统中&…

C#运算符重载

1、运算符重载 运算符重载是指重定义C#内置的运算符。 程序员也可以使用用户自定义类型的运算符。重载运算符是具有特殊名称的函数&#xff0c;是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样&#xff0c;重载运算符有返回类型和参数列表。 2、在Box类中定义…

C++ volatile 关键字

C volatile &#xff08;只有release下才会生效&#xff09; 1、告诉编译器volatile修饰的变量不要进行指令顺序的优化&#xff0c;以保证代码编写者的真实意图&#xff1b; int a 0;int b 10;int c 100;int* p &a;p &b;p &c;如果不加volatile修饰 p , 编译…

团队编程:提升代码质量与知识共享的利器

目录 前言1. 什么是团队编程&#xff1f;1.1 团队编程的起源1.2 团队编程的工作流程 2. 团队编程的优势2.1 提高代码质量2.2 促进知识共享2.3 增强团队协作2.4 提高开发效率 3. 团队编程的挑战3.1 开发成本较高3.2 需要良好的团队协作3.3 个人风格和习惯的差异3.4 长时间的集中…

AI时代算法面试:揭秘高频算法问题与解答策略

三种决策树算法的特点和区别 ID3算法&#xff1a;基本的决策树算法&#xff0c;适用于简单的分类问题C4.5算法&#xff1a;改进了ID3算法&#xff0c;适用于更复杂的分类问题&#xff0c;可以处理连续型数据和缺失值CART算法&#xff1a;更加通用的决策树算法&#xff0c;适用于…

【机器学习】机器学习与自然语言处理的融合应用与性能优化新探索

引言 自然语言处理&#xff08;NLP&#xff09;是计算机科学中的一个重要领域&#xff0c;旨在通过计算机对人类语言进行理解、生成和分析。随着深度学习和大数据技术的发展&#xff0c;机器学习在自然语言处理中的应用越来越广泛&#xff0c;从文本分类、情感分析到机器翻译和…

VBA常用的字符串内置函数

前言 在VBA程序中&#xff0c;常用的内置函数可以按照功能分为字符串函数、数字函数、转换函数等等&#xff0c;本节主要会介绍常用的字符串的内置函数&#xff0c;包括Len()、Left()、Mid()、Right()、Split()、String()、StrConV()等。 本节的练习数据表以下表为例&#xff…

前后端的导入、导出、模板下载等写法

导入&#xff0c;导出、模板下载等的前后端写法 文章目录 导入&#xff0c;导出、模板下载等的前后端写法一、导入实现1.1 后端的导入1.2 前端的导入 二、基础的模板下载2.1 后端的模板下载-若依基础版本2.2 前端的模板下载2.3 后端的模板下载 - 基于资源文件读取2.4 excel制作…

使用maven搭建一个SpingBoot项目

1.首先创建一个maven项目 注意选择合适的jdk版本 2.添加依赖 2.在pom.xml中至少添加依赖 spring-boot-starter-web 依赖&#xff0c;目的是引入Tomcat&#xff0c;以及SpringMVC等&#xff0c;使项目具有web功能。 <!-- 引入 包含tomcat&#xff0c;SpringMVC&#xff0c…

二维Gamma分布的激光点云去噪

目录 1、Gamma 分布简介2、实现步骤 1、Gamma 分布简介 Gamma 分布在合成孔径雷达( Synthetic Aperture &#xff32;adar&#xff0c;SA&#xff32;) 图像分割中具有广泛应用&#xff0c;较好的解决了SA&#xff32; 图像中相干斑噪声对图像分割的影响。采用二维Gamma 分布对…

配置基于不同端口的虚拟主机

更改配置文件&#xff0c;添加三个不同端口的虚拟主机 <directory /www> allowoverride none require all granted </directory><virtualhost 192.168.209.136:80> documentroot /www servername 192.168.209.136 </virtualhost><virtualhost 192.…

详解yolov5的网络结构

转载自文章 网络结构图&#xff08;简易版和详细版&#xff09; 此图是博主的老师&#xff0c;杜老师的图 网络框架介绍 前言&#xff1a; YOLOv5是一种基于轻量级卷积神经网络&#xff08;CNN&#xff09;的目标检测算法&#xff0c;整体可以分为三个部分&#xff0c; ba…

Floyd判圈算法——环形链表(C++)

Floyd判圈算法(Floyd Cycle Detection Algorithm)&#xff0c;又称龟兔赛跑算法(Tortoise and Hare Algorithm)&#xff0c;是一个可以在有限状态机、迭代函数或者链表上判断是否存在环&#xff0c;求出该环的起点与长度的算法。 …

实验四 图像增强—灰度变换之直方图变换

一&#xff0e;实验目的 1&#xff0e;掌握灰度直方图的概念及其计算方法&#xff1b; 2&#xff0e;熟练掌握直方图均衡化计算过程&#xff1b;了解直方图规定化的计算过程&#xff1b; 3&#xff0e;了解色彩直方图的概念和计算方法 二&#xff0e;实验内容&#xff1a; …

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【19】认证服务03—分布式下Session共享问题

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【19】分布式下Session共享问题 session原理分布式下session共享问题Session共享问题解决—session复制Session共享问题解决—客户端存储Session共享问题解决—hash一致性Session共享问题…

嵌入式linux面试1

1. linux 1.1. Window系统和Linux系统的区别 linux区分大小写windows在dos&#xff08;磁盘操作系统&#xff09;界面命令下不区分大小写&#xff1b; 1.2. 文件格式区分 windows用扩展名区分文件&#xff1b;如.exe代表执行文件&#xff0c;.txt代表文本文件&#xff0c;.…

Seatunnel本地模式快速测验

前言 SeaTunnel&#xff08;先前称为WaterDrop&#xff09;是一个分布式、高性能、易于扩展的数据集成平台&#xff0c;旨在实现海量数据的同步和转换。它支持多种数据处理引擎&#xff0c;包括Apache Spark和Apache Flink&#xff0c;并在某个版本中引入了自主研发的Zeta引擎…