[专题练习] Part1 搜索

一.DFS(深度优先搜索)

过于水略过。

二.BFS(广度优先搜索)

同上。

三.记忆化

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

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

四.搜索剪枝

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

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

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

所以考试打暴力的时候一定要多写剪枝,尤其是奇形怪状的玄学剪枝(参考i207m某次比赛的$N^2$跑过1e9)。

几道例题:

1. Noip2015斗地主  。

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

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

2.Noip2009靶形数独

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

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

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

通常使用的剪枝技巧

1.最优性剪枝。

2.$A*$剪枝。

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

五.双向广搜

正在研究中...

原文地址:https://www.cnblogs.com/BriMon/p/9768460.html

时间: 2024-11-03 23:45:41

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

专题一 简单搜索

本专题主要锻炼搜索的两大方法——bfs (宽度优先搜索)和 dfs (深度优先搜索) ===================================华丽的分割线======================================= 一.bfs——宽度优先搜索 bfs主要运用于搜索中求最短时间的问题,搜索过程中一般需要运用 queue 的操作.具体的操作如下: 1.首先需要将 队列 和 visit数组 清空.(这一点很重要!!!) 2.然后将起点信息 push 进队列,标记为vis

kuangbin带你飞专题一 简单搜索 题解

目录 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题一 简单搜索 总结:用时2天半终于把这个专题刷完了 对于最基础的dfs bfs 路径打印 状态转移也有了一点自己些微的理解 其实2天半可以压缩到1天半的 主要是自己太懒了...慢慢加油刷bin神的专题呀 从大二下学期开始学算法 一开始就知道这个专题 一开始对于这个专题里的所有问题感觉都好难啊..就直接放弃了 看lrj的书 现在看到这个专题还挺唏嘘的吧 突然觉得思维和想法也不是很难 果然是那个时候心不静&还是储量不够吗

专题一 简单搜索 Problem A

题目链接:http://poj.org/problem?id=1321 题目大意和N皇后类似,只不过可能出现K<N的情况. 按照行的顺序进行深搜,如果当前行可以放置棋子,则换下一行进行搜索. 用一个二维数组描述棋盘,一个一维数组标记此列是否走过. 1 #include<cstdio> 2 #include<cstdlib> 3 4 const int MAXN=8; 5 char m[MAXN][MAXN]; //记录棋盘 6 int vis[MAXN]; //标记每一列是否

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

1 //Memory Time 2 //2236K 32MS 3 4 #include<iostream> 5 using namespace std; 6 7 int mod[524286]; //保存每次mod n的余数 8 //由于198的余数序列是最长的 9 //经过反复二分验证,436905是能存储198余数序列的最少空间 10 //但POJ肯定又越界测试了...524286是AC的最低下限,不然铁定RE 11 12 int main(int i) 13 { 14 int n; 15

专题一 简单搜索 Problem B

题目链接:http://poj.org/problem?id=2251 题目大意:三维迷宫求两点间最短路. 解题思路:bfs搜索. 用一个三维数组maze记录迷宫的每一点是否可走. 用一个三维数组标记每一点是否已经走过. 用一个一维数组模拟队列的实现过程. 将起点放在队首,然后向六个方向扩展,若可行,则把该点放在队首,并抛弃队首成员. 如果当前点为终点,则记录下此时花费的时间,并返回. 代码如下: 1 #include<cstdio> 2 #include<cstring> 3 #

专题一 简单搜索 Problem K

题目链接:http://poj.org/problem?id=3984 题目大意:给定一个5*5的迷宫,其中有的点可走,有的点不可走,问从左上角到右下角所需要的最短步数. 并记录下该最短路径的整个过程. 解题思路:bfs搜索 由于这道题需要将路径打印出来,所以用一个结构体描述一点时,不仅需要记录该点的横纵坐标,还需要记录该点的上一个节点的编号. 从队首取出一点,向4个方向开始搜索,如果满足条件,将该点标记为走过,放入队尾,此时还要记录它的上一个点(head-1). 防止搜索越界.output函数

专题一 简单搜索 Problem F

题目链接:http://poj.org/problem?id=3126 题目大意:给定两个素数(四位数),求从第一个数变换到第二个数所需要的最小次数. 变换:每次允许变换个位/十位/百位/千位的其中一个数字.且保证变换完以后该数字仍然是素数. 解题思路:bfs搜索 每次从队首取出一个元素,向40个方向扩展(实际上只有34个方向),若满足条件,将其放入队尾. 直到找到该点,则返回此时一共走过的所有步数. 代码如下: 1 #include<cstdio> 2 #include<cmath&g

专题一 简单搜索 Problem C

题目链接:http://poj.org/problem?id=3278 题目大意:一条线上,给定起点和终点,求最短路径. 从当前点有三种选择,向左走一步,向右走一步,横坐标变为2倍. 解题思路:bfs搜索 将起点放在队首.每次从起点拿出一点,然后向三个方向扩展.如果满足条件,放入队尾. 如果该点满足,则返回总的步数. 代码如下: 1 #include<cstdio> 2 #include<cstring> 3 #define MAXN 200020 4 5 int n,k; 6 s

bin巨专题一 简单搜索(更新中

A--棋盘问题 POJ-1321 链接: https://vjudge.net/problem/15202/origin 类似n皇后问题,需要注意的是dfs的边界问题(t在此处 思路:当前走到i/u行j列,判断该点是否可以放棋子,不可以就j++,可以就dfs(i + 1),对放的棋子数进行计数,若等于k则return,记得状态还原. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 us