本文中的链接有的是题解有的是题目链接,已经搞混了...

一.DFS(深度优先搜索)

过于水略过。

二.BFS(广度优先搜索)

同上。

三.记忆化

记忆化搜索,就是我们的状态会重复利用,为了防止状态的重复计算耗费不必要的时间,我们可以把这个状态的结果记录下来,然后查询表中的结果就行了。

一般来所,记忆化搜索是和DP等价的。如果递推的DP不好写,可以考虑用记忆化搜索实现,但是因为是递归,所以常数略大。记忆化搜索有明显的优点,就是可以不用考虑状态在哪里终止,只用知道状态会终止就行了。

四.搜索剪枝

这是一门博大精深的学问, 通常用于解决搜索时间复杂度过高的问题。

原理就是在庞大的搜索树上剪去不可能对答案产生贡献的枝条。

搜索+剪枝的时间复杂度是$O(玄学)$,因为我们只能通过经验来估测剪枝效果。

所以考试打暴力的时候一定要多写剪枝,尤其是奇形怪状的玄学剪枝。

几道例题:

1. Noip2015斗地主  。

贪心出牌,出完顺子枚举出其他的尽可能出的多的牌的组合。

加上最优化剪枝,如果现在出了$ans-1$次没有出完就剪枝。

2.Noip2009靶形数独

我当时用了$lowbit$优化常数,然后把整个棋盘分成上下两部分,如果上半部分空位比下半部分多,就从下半部开始搜索。这样就水过去了。

其实也可以按格搜索,优先搜可填的少的格。

还有$A^*$剪枝,如果剩下的格子都填9还比$ans$小的话就剪枝。

通常使用的剪枝技巧

1.最优性剪枝。

2.$A^*$剪枝。

3.改变搜索顺序,优先搜索扩展出的状态比较少的状态。

五.双向广搜

双向广搜就是从起点和终点开始搜索,每次各搜一层,如果相遇,则得出答案。

双向广搜可以使搜索树减少一半以上,大大优化了时间复杂度。

广度双向搜索通常有两种方法:

  1. 两个方向交替扩展

  2. 选择结点个数较少的那个方向先扩展.

方法2克服了两方向结点的生成速度不平衡的状态,明显提高了效率。

1.poj3523The Morning after Halloween

其实这题直接$bfs$就可过,但是为了追求效率,用双向广搜甚至可以减少一半的时间。

六.meet in the middle

这个和双向搜索有差别,思路是把问题折半,然后合并,减少一半的搜索层数。

经典例题NOI2001方程的解数

先搜前3个解,把结果用hash表存一下,然后搜后3个解,在hash表中查询个数。

这题太恶心了,用mapT飞,用hash表Mle,大力取模WA。

无药可救...

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <map>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
#define reg register
inline int read() {
int res=;char ch=getchar();bool fu=;
while(!isdigit(ch))fu|=(ch=='-'), ch=getchar();
while(isdigit(ch))res=(res<<)+(res<<)+(ch^),ch=getchar();
return fu?-res:res;
} int n, m;
int k[], p[];
int mi[][];
int ans;
map <int, int> mp;
void dfs1(int dep, int sum)
{
if (dep > n / ) {
mp[sum]++;
return ;
}
for (reg int i = ; i <= m ; i ++)
dfs1(dep + , sum + k[dep] * mi[i][p[dep]]);
} void dfs2(int dep, int sum)
{
if (dep > n) {
ans += mp[-sum];
return ;
}
for (reg int i = ; i <= m ; i ++)
dfs2(dep + , sum + k[dep] * mi[i][p[dep]]);
} int main()
{
n = read(), m = read();
for (reg int i = ; i <= n ; i ++) k[i] = read(), p[i] = read();
for (reg int i = ; i <= m ; i ++)
{
mi[i][] = ;
for (reg int j = ; j <= m ; j ++) mi[i][j] = mi[i][j - ] * i;
}
dfs1(, );
dfs2(n / + , );
cout << ans << endl;
return ;
}

方程的解数

七.迭代加深搜索(IDDFS)

某些题状态无限,bfs无法承受空间复杂度,可以限制dfs搜索的深度。

每次增加深度限制,每次可能对之前搜过的状态多次计算,但是由于状态每一层都扩展的十分多,所以相比于扩展一层,重复上面的状态的复杂度还是可以接受的。

1.codevs1288 埃及分数

可以逐步增加答案的分数的个数,然后可以限制住状态的无限扩展...其实我不会233(逃.

2.poj2248 Addition Chains   (此题解访问人数已经突破100人啦!!)

和上面一样逐步扩展答案的个数,然后再加上一些十分有用的剪枝,才能A掉这题,详情见链接。

八.迭代加深A*(IDA*)

普通迭代加深搜索加入A*剪枝。

1.bzoj1085 骑士精神

估价函数的一小点变动可能导致时间上的很大的差别,详情点进链接看看。

2.poj2286The Rotation Game

估价函数为8-中间出现次数最多的数字的个数。

九.随机化

过于玄学,略过。

[专题练习] Part1 搜索的更多相关文章

  1. Leetcode之回溯法专题-212. 单词搜索 II(Word Search II)

    Leetcode之回溯法专题-212. 单词搜索 II(Word Search II) 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单 ...

  2. Leetcode之回溯法专题-79. 单词搜索(Word Search)

    Leetcode之回溯法专题-79. 单词搜索(Word Search) 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元 ...

  3. [kuangbin带你飞]专题一 简单搜索 题解报告

    又重头开始刷kuangbin,有些题用了和以前不一样的思路解决.全部题解如下 点击每道题的标题即可跳转至VJ题目页面. A-棋盘问题 棋子不能摆在相同行和相同列,所以我们可以依此枚举每一行,然后标记每 ...

  4. kuangbin专题 专题一 简单搜索 Oil Deposits HDU - 1241

    题目链接:https://vjudge.net/problem/HDU-1241 题意:问有几个油田,一个油田由相邻的‘@’,组成. 思路:bfs,dfs都可以,只需要遍历地图,遇到‘@’,跑一遍搜索 ...

  5. kuangbin专题 专题一 简单搜索 迷宫问题 POJ - 3984

    题目链接:https://vjudge.net/problem/POJ-3984 这个题目,emm,上代码,看的估计应该是刚开始接触搜索的,我带点注释,你能慢慢理解. #include <ios ...

  6. [kuangbin带你飞]专题一 简单搜索 - E - Find The Multiple

    //Memory Time //2236K 32MS #include<iostream> using namespace std; ]; //保存每次mod n的余数 //由于198的余 ...

  7. Leedcode算法专题训练(搜索)

    BFS 广度优先搜索一层一层地进行遍历,每层遍历都是以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点.需要注意的是,遍历过的节点不能再次被遍历. 第一层: 0 -> {6,2,1,5} ...

  8. [kuangbin带你飞]专题一 简单搜索 棋盘问题

    题来:链接https://vjudge.net/problem/OpenJ_Bailian-132 J - 棋盘问题 1.题目: 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别. ...

  9. [kuangbin带你飞]专题一 简单搜索

            ID Origin Title 454 / 1008 Problem A POJ 1321 棋盘问题   328 / 854 Problem B POJ 2251 Dungeon Ma ...

随机推荐

  1. kubernetes部署高可用Harbor

    前言 本文Harbor高可用依照Harbor官网部署,主要思路如下,大家可以根据具体情况选择搭建. 部署Postgresql高可用集群.(本文选用Stolon进行管理,请查看文章<kuberne ...

  2. 从零开始入门 K8s| 详解 Pod 及容器设计模式

    作者|张磊 阿里云容器平台高级技术专家,CNCF 官方大使 一.为什么需要 Pod 容器的基本概念 我们知道 Pod 是 Kubernetes 项目里面一个非常重要的概念,也是非常重要的一个原子调度单 ...

  3. JavaScript学习记录

    js整理笔记 1.数据类型 2.基本语法 3.js运算符 4.条件语句 5.类型转换 6.函数 7.预编译 8.作用域 9.闭包 10.对象创建方法 11.this 12.dom操作 13.事件 14 ...

  4. 基于Docker搭建大数据集群(二)基础组件配置

    主要内容 jdk环境搭建 scala环境搭建 zookeeper部署 mysql部署 前提 docker容器之间能免密钥登录 yum源更换为阿里源 安装包 微云分享 | tar包目录下 JDK 1.8 ...

  5. electron教程(一): electron的安装和项目的创建

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(二): http服务器, ws服务器, 进程管理 electron教程(三): 使 ...

  6. SpringBootSecurity学习(08)网页版登录整合MyBatis

    创建数据库 前面介绍了springboot-security整合jdbc从数据库中查询用户的方式,适用性有限,下面介绍最常用的整合MyBatis,这种在开发和生产环境中是最常用,也是最实用的.首先需要 ...

  7. Spring框架(三)

    对象依赖关系 Spring中,如何给对象的属性赋值?  [DI, 依赖注入] 1) 通过构造函数 2) 通过set方法给属性注入值 3) p名称空间 4)自动装配(了解) 5) 注解 代码示例: &l ...

  8. CVPR 2019 论文解读 | 小样本域适应的目标检测

    引文 ​ 最近笔者也在寻找目标检测的其他方向,一般可以继续挖掘的方向是从目标检测的数据入手,困难样本的目标检测,如检测物体被遮挡,极小人脸检测,亦或者数据样本不足的算法.这里笔者介绍一篇小样本(few ...

  9. javascript中字符串对象常用的方法和属性

    前言 字符串是一种非常重要的数据类型,在Java等面向对象编程语言中,它代表对象类型,而在javascript中它却是一种基本数据类型,在开发的领域中,我们经常会碰到,无论是前端还是后台.比如后台验证 ...

  10. golang 你所不知道的 log 和 fmt

    直接点说,就是由于fmt 是线程不安全的, 如果你在多协程场景下使用fmt打印信息可能会得到乱序的结果 就是说 不按代码里的顺序打印. 下面看示例 代码示例 golang fmt 多线程 乱序: fu ...