搜索(5):迭代加深、双向dfs

news2024/11/20 1:29:49

活动 - AcWing   + 算法竞赛进阶指南

一、迭代加深概述

dfs每次选定一个分支,直到抵达递归边界才回溯,这种策略有一定缺陷。当搜索树的某个分支情况非常多,并且问题的答案在一个较浅的分支上时,如果一开始就选错了分支,那么就会在没有答案的子树上浪费很多时间。

因此我们可以从小到大限制搜索的深度,如果在当前深度限制下搜不到答案,就把深度限制增加,重新搜索。这就是迭代加深的思想。

迭代就是以上次的结果为基础,重复执行以逼近答案的意思。

总之,当搜索树的规模随着层次的深入增长很快,并且我们能够确保答案在一个较浅层的节点时,就可以采用迭代加深dfs。

二、例题:acwing170加成序列

主要信息:

  • 开始是1,结尾是指定的n
  • 严格递增
  • 必须满足是第k个数是前面某两个数相加可得到,这两个数可以是同一个数

可以推算,因为n小于100,加成序列的长度不会很长(2的次方逼近),因此考虑迭代加深算法。

直觉做法:大框架:设定迭代加深深度depth即序列长度,从1开始,不行就++。对每个depth深搜一次,True了就停止然后输出序列。

搜索框架:从小到大枚举序列的位置,对第k个数,枚举前面的位置i,j(i,j可以相等),得出第k个数所有的可能取值s。然后搜索下一个位置。当位置大于depth时返回false,当当前位置选了n时返回true

细节处理:对于可能取值s,要求s递增,s不能重复,s小于n

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N =110;

int n;
int path[N];

bool dfs(int u,int depth)
{
    if(u>depth) return false;
    if(path[u-1]==n) return true;

    bool st[N]={0};
    for(int i=u-1;i>=0;i--)
        for(int j=i;j>=0;j--)
        {
            int s=path[i]+path[j];
            if(s>n||st[s]||s<=path[u-1]) continue;

            st[s]=true;
            path[u]=s;
            if(dfs(u+1,depth)) return true;  //不需要恢复现场因为bool数组是局部变量
        }
    return false;
}


int main()
{
    path[0]=1;
    while(cin>>n,n)
    {
        int depth=1;
        while(!dfs(1,depth)) depth++;

        for(int i=0;i<depth;i++) cout<<path[i]<<" ";
        cout<<endl;
    }
    return 0;
}

作者:yankai
链接:https://www.acwing.com/activity/content/code/content/4231905/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三、双向dfs概述

图片来自:AcWing 171. 送礼物 - AcWing        

 四、双向dfs例题:

 题目意思:从N个数中选几个数,使得结果最接近W但不大与W。可以用背包问题求解,但是这里Gi太大了,做不了。

考虑搜索算法,最直接的算法就是直接枚举每个物品选或者不选,那么就有2^46种状态,复杂度过高。这时我们就可以考虑用双向dfs将搜索树分成两半。

首先我们先从前一半礼物中选出若干个,可能达到的0~W之间的所有重量记录在A中,然后对A进行排序、去重

然后尝试从后一半礼物中选出一些,对于买个可能的重量值t,在第一部分的A数组中二分查找小于等于W-t的最大的一个数,用他们的和更新答案。

这个算法的复杂度就是只有O(2^{N/2}log2^{N/2})。

还可以加入一些之前提过的优化提高算法效率:

1.优化搜索顺序,先把礼物按重量降序排序,分半

2.选取合适的折半搜索点。。因为二次搜索需要在第一次搜索中得到的数组进行二分查找,效率相对较低。因此我们应该稍微增加第一次搜索的礼物数,减少第二次搜索的礼物数。经过测试,取第1~N/2+2个礼物为“前一半”时搜索速度最快。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N =50;
typedef long long LL;

int n,m,k;
int w[N];
int weights[1<<24],cnt=0;
int ans;

void dfs1(int u,int s)
{
    if(u==k)
    {
        weights[cnt++]=s;
        return;
    }
    
    if((LL)s+w[u]<=m) dfs1(u+1,s+w[u]);
    dfs1(u+1,s);
}

void dfs2(int u,int s)
{
    if(u==n)
    {
        int l=0,r=cnt-1;
        while(l<r)
        {
            int mid=l+r+1>>1;
            if(weights[mid]+(LL)s<=m) l=mid;
            else r=mid-1;
        }
        if(weights[l]+(LL)s<=m) ans=max(ans,weights[l]+s);
        return;
    }
    
    if((LL)s+w[u]<=m) dfs2(u+1,s+w[u]);
    dfs2(u+1,s);
    
}

int main()
{
    cin>>m>>n;
    for(int i=0;i<n;i++) cin>>w[i];
    
    sort(w,w+n);
    reverse(w,w+n);
    
    k=n/2;
    dfs1(0,0);
    
    sort(weights,weights+cnt);
    int t=1;
    for(int i=1;i<cnt;i++)
        if(weights[i]!=weights[i-1])
            weights[t++]=weights[i];
    cnt=t;
    
    dfs2(k,0);
    
    cout<<ans<<endl;
    return 0;
    
    
}

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

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

相关文章

在宜宾,看见未来中国的产融平台样本

在被验证的京东西南数字化产融协同平台背后&#xff0c;恰证明着在京东这样的新型实体企业支持下&#xff0c;中国的区域产业经济已经出现星星之火&#xff0c;而这些星星之火正在帮助成千上万的企业走出固有的销售渠道和销售模型&#xff0c;成为新时代数字经济和产业经济的一…

单芯片快速以太网MAC控制器DM9000介绍

DM9000简介 DM9000是一款完全集成的和符合成本效益单芯片快速以太网MAC控制器与一般处理接口&#xff0c;一个10/100M 自适应的PHY 和4K DWORD 值的SRAM。它的目的是在低功耗和高性能进程的3.3V与5V的支持宽容。 DM9000 还提供了介质无关的接口&#xff0c;来连接所有提供支持介…

javaee之spring2

基于注解的IOC配置 一、先来说一下放在对象上面的注解 Component: * 作用&#xff1a;用于把当前类对象存入spring容器中 * 属性&#xff1a; * value&#xff1a;用于指定bean的id。当我们不写时&#xff0c;它的默认值是当前类名&#xf…

RabbitMQ 第一天 基础 5 Spring 整合RabbitMQ 5.2 Spring 整合 RabbitMQ【消费者】 5.3 小结

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第一天 基础5 Spring 整合RabbitMQ5.2 Spring 整合 RabbitMQ【消费者】5.2.1 消费者5.3 小结第一天 基础 5 Spring 整合RabbitMQ 5.2 Spring 整合 RabbitMQ【消费者】 5.2.1…

白话说Java虚拟机原理系列【第五章】:内存结构之堆详解

文章目录堆(Heap)对象在堆中的存储结构垃圾收集器详解对象存活判断算法引用的种类对象最终判定死亡之两次标记规则方法区的垃圾回收原则垃圾收集算法分代收集模型垃圾收集器对象分配原则垃圾收集触发方式垃圾收集器的参数异常前导说明&#xff1a; 本文基于《深入理解Java虚拟机…

大数据分析案例-基于逻辑回归算法构建垃圾邮件分类器模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【Django】第二课 基于Django超市订单管理系统开发

概念 本文在上一文之上&#xff0c;针对管理员&#xff0c;经理&#xff0c;普通员工身份的用户操作用户管理模块功能。 功能实现 1.普通员工登录系统后&#xff0c;对于用户管理模块不具备操作其他用户信息的权限。因此当普通员工登录后&#xff0c;弹出对话框提示用户。 2…

【Linux】Linux编辑器---vim的使用

等老了就养只柴犬&#xff0c;相依为命。 文章目录一、命令模式1.光标定位操作2.文本复制、粘贴、剪切、撤销3.文本编辑二、插入模式三、底行模式四、vim配置原理五、解决普通用户无法使用sudo提权一、命令模式 刚打开vim时&#xff0c;默认就是命令模式&#xff0c;命令模式的…

C++STL之string的使用

对于C语言中的字符串&#xff0c;我们只能使用char类型数组保存&#xff0c;并且是以\0结尾的. 操作起来非常不方便而且底层空间需要用户自己访问&#xff0c;非常造成容易越界访问. 这个时候&#xff0c;C的STL中的string类就很好解决了这些. 目录 string的使用 1.string…

mqtt的使用与二次封装

前提&#xff1a;先安装Mosquitto并启动服务&#xff0c;可使用mqttx进行接收发送的测试。 Mosquitto以配置启动命令 mosquitto -c mosquitto.conf -v原文链接&#xff1a;mqtt的使用 本文为测试使用固无账号密码&#xff0c;可在原文查看 封装后实现效果&#xff0c;加入一个…

LeetCode题解 16(15,22) 三数之和,括号生成

文章目录三数之和(15)代码解答:括号生成(22)代码解答:三数之和(15) 该题是让从1个数组中找到和为0的不重复的三个数,这次我们使用排序和指针的方法来解决 先将该数组从小到大进行排序 Arrays.sort(nums);我们需要遍历一遍该数组,同时我们还要去重的操作(例如[-1,-1,-1,2],这里面…

helm本地debug template渲染小记

前提条件 1&#xff0c; 安装helm 2&#xff0c;要能连接的k8s 3&#xff0c;本地有完成charts文件目录 具体步骤 本文因为是在项目流程中helm渲染出的deployment语法报错或者最终生成的不符合预期&#xff0c;因此本地使用helm命令进行debug验证测试。 我们先看一下基本的c…

怎么把word里面的彩色图转化为灰度图,直接在word里面操作,无需转其他软件,超简单!(位图和矢量图都可以)

怎么把word里面的彩色图转化为灰度图&#xff0c;直接在word里面操作&#xff0c;无需转其他软件&#xff0c;超简单&#xff01;&#xff08;位图和矢量图都可以&#xff09; Microsoft Office Word是微软公司的一个文字处理器应用程序。它最初是由Richard Brodie为了运行DOS…

深入理解自编码器(用变分自编码器生成图像)

文章目录自编码器欠完备自编码器正则自编码器稀疏自编码器去噪自编码器收缩自编码器变分自编码器References内容总结自花书《Deep Learning》以及《Python 深度学习》。 自编码器 自编码器&#xff08;autoencoder&#xff09;是神经网络的一种&#xff0c;经过训练后能尝试将…

机器学习经典算法:决策树(2)

1. 概述 决策树&#xff08;Decision Tree&#xff09;是有监督学习中的一种算法&#xff0c;并且是一种基本的分类与回归的方法。决策树有两种&#xff1a;分类树和回归树。 决策树是用于分类和回归的工具&#xff0c;它将数据特征值拆分为决策节点处的分支&#xff08;例如&a…

六、Kubernetes核心技术Pod详解、实例

1、概述 Pod 是 k8s 系统中可以创建和管理的最小单元&#xff0c;是资源对象模型中由用户创建或部署的最 小资源对象模型&#xff0c;也是在 k8s 上运行容器化应用的资源对象&#xff0c;其他的资源对象都是用来支 撑或者扩展 Pod 对象功能的&#xff0c;比如控制器对象是用来管…

某大型政务网站的优化咨询案例(视频点播VOD+GZIP压缩+静态文件CDN+Redis缓存+全文索引)

2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ 这次分享关于一个对某大型政务网站的优化咨询的案例&#xff0c;发生在今年的下半年&#xff0c;已过去一段时间&#xff0c;并取得了良好的成果&#xff01;* 项目背景 某大型政务网站准备上线&#xff0c;需要…

08-Golang中的运算符

[TOC](Golang中的运算符运算符介绍算数运算符基本介绍细节说明关系运算符(比较运算符&#xff09;基本介绍细节说明逻辑运算符基本介绍细节说明赋值运算符基本介绍细节说明运算符优先级运算符介绍 运算符是一种特殊的符号&#xff0c;用来表示数据的运算、赋值和比较 1.算数运…

Vue事件处理的基本使用

前言 事件处理在vue中也是非常重要的一项技术&#xff0c;它类似于js的事件处理&#xff0c;但是也有不同&#xff0c;下面就简单介绍一下在vue中如何进行事件使用以及一些要点 1 事件基本使用 在这里我们使用单击事件为例&#xff0c;简单讲讲在vue中单击事件的编写以及细节…

最近面试遇到一个算法题,简单写一点。

第⼀题&#xff08;必答&#xff09; 请针对有重复数字的数组设计⼀个快排算法&#xff0c;⽐如&#xff1a;[34, 34, 89, 1, 1, 20, 12]&#xff0c;排序后结果为 [89,34,34,20,12,1,1] 第⼆题&#xff08;必答&#xff09; 请利⽤Redis 实现⼀个通⽤分布式锁&#xff0c;并…