博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[专题练习] Part1 搜索
阅读量:5171 次
发布时间:2019-06-13

本文共 2424 字,大约阅读时间需要 8 分钟。

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

一.DFS(深度优先搜索)

过于水略过。

二.BFS(广度优先搜索)

同上。

三.记忆化

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

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

四.搜索剪枝

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

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

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

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

几道例题:

  。

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

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

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

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

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

通常使用的剪枝技巧

1.最优性剪枝。

2.$A^*$剪枝。

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

五.双向广搜

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

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

 

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

 

  1. 两个方向交替扩展

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

 

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

 

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

六.meet in the middle

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

经典例题

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

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

无药可救...

#include 
#include
#include
#include
#include
#include
#include
#include
using namespace std;#define reg registerinline int read() { int res=0;char ch=getchar();bool fu=0; while(!isdigit(ch))fu|=(ch=='-'), ch=getchar(); while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar(); return fu?-res:res;}int n, m;int k[8], p[8];int mi[155][155];int ans;map
mp;void dfs1(int dep, int sum) { if (dep > n / 2) { mp[sum]++; return ; } for (reg int i = 1 ; i <= m ; i ++) dfs1(dep + 1, sum + k[dep] * mi[i][p[dep]]);}void dfs2(int dep, int sum) { if (dep > n) { ans += mp[-sum]; return ; } for (reg int i = 1 ; i <= m ; i ++) dfs2(dep + 1, sum + k[dep] * mi[i][p[dep]]);}int main(){ n = read(), m = read(); for (reg int i = 1 ; i <= n ; i ++) k[i] = read(), p[i] = read(); for (reg int i = 0 ; i <= m ; i ++) { mi[i][0] = 1; for (reg int j = 1 ; j <= m ; j ++) mi[i][j] = mi[i][j - 1] * i; } dfs1(1, 0); dfs2(n / 2 + 1, 0); cout << ans << endl; return 0;}
方程的解数

七.迭代加深搜索(IDDFS)

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

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

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

   (此题解访问人数已经突破100人啦!!)

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

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

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

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

2.poj2286

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

九.随机化

过于玄学,略过。

转载于:https://www.cnblogs.com/BriMon/p/9768460.html

你可能感兴趣的文章
HDU1760 A New Tetris Game NP态
查看>>
css3 选择器
查看>>
在SQL Server 语句中,如何将参数做为表名传递到查询语句中
查看>>
“System.AccessViolationException”类型的未经处理的异常在 System.Data.dll 中发生
查看>>
Android Studio 自定义字体显示英文音标
查看>>
登录首页时报错:java.lang.IllegalArgumentException (不合法的参数异常)
查看>>
【深度解析】Google第二代深度学习引擎TensorFlow开源
查看>>
block
查看>>
作业三——改进目标
查看>>
【校园电子书城】测试及部署
查看>>
WAMP(Windows+Apache+Mysql+PHP)环境搭建
查看>>
golang调用c++的dll库文件
查看>>
知识点篇:7)企业标准体系制定要求
查看>>
php’s explode() 函数
查看>>
Spring AOP的实现思想之动态代理
查看>>
VSCode设置中文语言
查看>>
Kafka 几个实现细节
查看>>
UWP学习目录整理
查看>>
Centos7-安装Gradle4.10
查看>>
四则运算1
查看>>