搜索:

一种基础的算法。

考察常见于NOIP

但是高级的搜索算法可能还会在省选出现。

50%以上的暴力都可以用搜索直接枚举来写。

但是,当数据规模不是很大的时候,搜索也可能成为正解。

(比如剪枝PK状压dp)

在搜索的基础上,可以衍生出最短路,而dp本质上,也是搜索的剪枝。

一、基础搜索算法

DFS:

最基本的搜索。用递归实现。

顾名思义,深度优先搜索的特点就是从一个位置直接搜下去,直到搜到末尾或者中途return

先扩展出深度。

dfs图中遍历的状态会形成一棵搜索树。(如果搜成了一般图,那就说明剪枝不到位了)

一般认为,dfs的复杂度就是“搜索树的大小 乘上 每一个状态 下的复杂度”

搜索的优点:可以不用记录状态。开一个全局变量即可。所有的函数也可以围绕这个变量展开。

自我感觉,dfs的更多时候,用途不在于搜索,而在于对结构的遍历。

用途:

1.50%的暴力,2^n,n!的枚举。

2.容斥。

3.遍历。

dfs遍历一棵树(可能爆栈),(求dfs序,树形dp等)

因为dfs会搜完一棵子树再回溯,所以利用这个性质,dfn,dfn2,以及tarjan都可以成立。

利用递归的性质,从儿子回溯后,对这一层的检查与更新,也是经常用到的。

4.配合BFS,寻找联通块

BFS:

最基本的遍历图的方法。一般用于搜索。

顾名思义,广度优先搜索,就是先扩展整个图的层数。

会从一个起点(多个起点)开始,不断把周围一层遍历,

即,遍历的状态的层数总是连续的一段。

用途:

1.边权为1的最短路。

这个其实是值得注意的,BFS的最短路是O(n+m)的,是所有的最短路中最快的。(有时那SPFA或者dij跑边权为1的最短路,就浪费了~~~)

当然,必须边权是1。

2.分层图:
利用BFS的分层图的性质,可以有层次地遍历一个结构。

AC自动机的fail树的构建:由于分层图,而fail[i]一定长度比i小,即层的编号小,所以必然已经遍历,没有后效性。

DINIC算法,在分层图上跑增广路。可以保证复杂度。

问题:

1.DFS的劣势明显,会进入一个搜索子树,遍历完这棵搜索树之后才会回溯。

如果这棵搜索树对答案不能产生影响,那么会大大降低效率。

更糟糕的,如果一棵子树非常庞大(指数级增长),则直接TLE地飞起。

2.BFS的劣势明显,由于要广度优先搜索,所以会遍历完整个一层才会遍历下一层。

如果一层很多,也会爆炸。

而且,必须记录所有当前在队列里状态的状态信息。

如果状态增多,搜索树较大,空间和时间都没有办法保证。

对于这些bug,机智的人们创建了新的优化方法。

二、剪枝

剪枝,顾名思义,就是在dfs或者bfs中,把一棵搜索子树直接砍去,不进行遍历。

来达到复杂度的保证。

其实剪枝范围可以很广,A*,IDA*,甚至dp,我认为都可以叫剪枝。

而且剪枝也不一定用于搜索。

当然,一般情况下的剪枝,就是指用dfs搜索中的剪枝。

1.最优性剪枝。

最常见。最基本的,对于单增取min,单减取max,都可以稳定减去一些复杂度。

配合估价函数,IDA*,对未来最少花费进行预估,通常可以大大增加效率。

2.可行性剪枝。

对于状态搜索下去是否能合法的剪枝。

3.预处理。

这个是经常忘记的,但是非常有用的“剪枝”

因为,通常搜索题的规模不大,扫一遍地图预处理根本不是瓶颈。

而由于搜索过程中,同一个位置可能遍历多次。每次再找合法的解,就很慢了。

经典例题BFS预处理:华容道

剪枝最重要的还是分析题目的性质。

剪枝能提前判断就提前判断。

例题:NOIP2004 虫食算

Mayan游戏

生日蛋糕

三、搜索进阶

其实都是剪枝。

A*,IDA*,迭代加深复杂度都是玄学。

和经验、人品、数据湿度成正比。

1.折半爆搜

dfs。举例,n大概在40左右,可以2^(n/2)爆搜。存储状态,然后可以合并。

蓝色是一般的正向搜索,两边dfs是红色和绿色部分。可以节省很多分支。

难点:状态存储和合并。

存储:数组,大了用map

合并:在dfs2到头的时候合并,或者可以搜完之后把状态sort,然后双指针等等。

例题:POJ1186 折半爆搜+双指针

2.双向广搜

bfs。对于走迷宫等状态可逆的题目类型

bfs1走一层,bfs2走一层,循环往复,直到在bfs1中碰到bfs2走过的路径或者反之,就可以停止。

通常适用于有固定起点和终点的。

通常使用哈希表存储经过路径。

例题:万圣节后的早晨&&九数码游戏——双向广搜

3.A*

思想:和BFS结合,设计一个估价函数。对未来的最小步数进行估价,估价函数h(S),实际代价g(S)。

每次选择g(S)+h(S)最小的进行扩展

第一次到达终点的就是最优解。

估价函数必须小于等于实际最小代价。否则可能会代替最优解,或者说,第一次到终点的不是最优解。

例题:
k短路,扩展一下,第k次到终点的就是第k短。

八数码,不同的位置数字个数作为估价。

4.迭代加深搜索。

有的时候,一个搜索树的增长非常迅速,子树非常庞大。

甚至子树是无穷大的。。。。

dfs会陷入其中无法自拔。

那么,如果问题答案步数不会很多(15步以内),甚至有提示:x步以内无解则-1

很可能就是迭代加深搜索。

有什么用?

限制搜索的深度,使得dfs在到达深度的时候,就会回溯。

重复搜索?

是的。但是比起庞大的树来说,不算什么。

5.IDA*

说是A*,但是主要是A*估价函数的思想。

因为是dfs,并没有像A*一样每次拓展最小的。

说白了,就是在迭代加深的dfs中,在剪枝里加入对未来步数的估价,

限制是:当前深度+预估步数>迭代上限,return

由于当前深度不会太深,所以可以很快判断return

传说非常好用。

例题:埃及分数&&The Rotation Game&&骑士精神——IDA*

四、正确性玄学算法

略。

[学习笔记]搜索——模拟与dp的结合的更多相关文章

  1. 【学习笔记】动态规划—各种 DP 优化

    [学习笔记]动态规划-各种 DP 优化 [大前言] 个人认为贪心,\(dp\) 是最难的,每次遇到题完全不知道该怎么办,看了题解后又瞬间恍然大悟(TAT).这篇文章也是花了我差不多一个月时间才全部完成 ...

  2. 汇编入门学习笔记 (七)—— dp,div,dup

    疯狂的暑假学习之  汇编入门学习笔记 (七)--  dp.div.dup 參考: <汇编语言> 王爽 第8章 1. bx.si.di.和 bp 8086CPU仅仅有4个寄存器能够用 &qu ...

  3. 「学习笔记」wqs二分/dp凸优化

    [学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...

  4. Python爬虫学习笔记之模拟登陆并爬去GitHub

    (1)环境准备: 请确保已经安装了requests和lxml库 (2)分析登陆过程:     首先要分析登陆的过程,需要探究后台的登陆请求是怎样发送的,登陆之后又有怎样的处理过程.      如果已经 ...

  5. [学习笔记]四边形不等式优化DP

    形如$f[i][j]=min{f[i][k]+f[k+1][j]}+w[i][j]$的方程中, $w[\;][\;]$如果同时满足: ①四边形不等式:$w[a][c]+w[b][d]\;\leq\;w ...

  6. android学习笔记18——dpi、dp、sp、xp......

    参考:http://www.cnblogs.com/greatverve/archive/2011/12/28/android-dip-dp-sp-pt-px.html  http://www.360 ...

  7. Java-马士兵设计模式学习笔记-观察者模式-模拟Awt Button

    一.概述 Java 的Awt是 Observer模式,现用Java自己模拟awt中Button的运行机制 二.代码 1.Test.java import java.text.DateFormat; i ...

  8. 学习笔记:状态压缩DP

    我们知道,用DP解决一个问题的时候很重要的一环就是状态的表示,一般来说,一个数组即可保存状态.但是有这样的一些题 目,它们具有DP问题的特性,但是状态中所包含的信息过多,如果要用数组来保存状态的话需要 ...

  9. 【Python自然语言处理】第一章学习笔记——搜索文本、计数统计和字符串链表

    这本书主要是基于Python和一个自然语言工具包(Natural Language Toolkit, NLTK)的开源库进行讲解 NLTK 介绍:NLTK是一个构建Python程序以处理人类语言数据的 ...

随机推荐

  1. testNG-失败用例重跑机制

    下面简单介绍下testNG的失败重跑的实现方法: 1.首先编写一个类,实现IRetryAnalyzer类,重写其中的retry方法. public class TestNGRetry implemen ...

  2. Phaser3让超级玛丽实现轻跳、高跳及加上对应的跳跃声音

      mario jumper 在线测试地址:http://www.ifiero.com/uploads/phaserjs3/jumper/ 空格键:轻按:跳低 ,长按:跳高键盘:--> 向右 , ...

  3. Lua学习笔记(5): 表

    表的初始化方式 表的索引类型一般有两种,一种是通过标识符访问,一种是通过数字访问 --通过标识符访问的表的初始化 table1 = {key_1 = "haha", key_2 = ...

  4. JavaScript事件冒泡和捕获

    事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件. 事件冒泡是自下而上的去触发事件. 绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获.true,事件捕获:fa ...

  5. hadoop2.7.1安装和部署

    操作系统:Red Hat Enterprise Linux Server release 6.2 (Santiago) hadoop2.7.1 三台redhat linux主机,ip分别为10.204 ...

  6. C++数字三角形问题与dp算法

    题目:数字三角形 题目介绍:如图所示的数字三角形,要求从最上方顶点开始一步一步下到最底层,每一步必须下一层,求出所经过的数字的最大和. 输入:第一行值n,代表n行数值:后面的n行数据代表每一行的数字. ...

  7. [T-ARA][Falling U]

    歌词来源:http://music.163.com/#/song?id=27506041 作词:韩尚元 [作词:韩尚元] 作曲:韩尚元 [作曲:韩尚元] Love is pain Love is pa ...

  8. 用vsstudio 设计Winform 高分屏上布局错乱的问题

    在使用win10高分辨率150%,200%系统进行winform开发时, 会有布局错乱的现象,比如之前定义的300px的宽度,往往被设置成600px (200%分辨率下). 这个问题vs2015的解决 ...

  9. 20172305 2018-2019-1 《Java软件结构与数据结构》第六周学习总结

    20172305 2018-2019-1 <Java软件结构与数据结构>第六周学习总结 教材学习内容总结 本周内容主要为书第十章内容: 树(一种非线性结构,其中的元素被组织成一个层次结构) ...

  10. Android开发设计 实验报告

    20162315 Android开发设计 实验报告 实验内容 1.安装 Android Stuidio,完成Hello World, 要求修改res目录中的内容,Hello World后要显示自己的学 ...