搜索算法

可以说几百年没去练过的东西了。但事实证明还挺有用的。

Meet in the Middle

以前一直没想通过双向搜索是怎么优化复杂度的。

例题 1

我称其为合法子集计数问题。

双向搜索就是把集合劈成两半,两边分别枚举子集,然后再记两两匹配的合法关系。

当后者可以快速统计时,双向搜索就优化了复杂度。

例题 2

三种状态:-1,1,0 在第一个、在第二个和根本不在。

合法子集计数,考虑劈成两半。于是任意两边可以获得 pair,然后就做完了。

A*

又名“启发式搜索”。

A* 理论其实蛮有意思的。

\(f_i=g_i+h_i\)

其中 \(g_i\) 表示从启示状态到来的实际代价,\(h_i\) 表示到达终止状态的估价函数。

要求 \(h_i\le d_i\)\(d_i\) 是到底终止状态的实际代价。

每次选取 \(f_i\) 最小的转移。

如果 \(h_i\) 满足三角不等式,则状态不会重复。

\(h_i=0\) 时,相当于做 dij。

\(h_i\) 的相对关系越接近 \(d_i\) 的相对关系,效率越高。

ID

又名“迭代加深搜索”。

其实就是设定深度以后 dfs 代替 bfs。

常用于空间不足时或是答案大概率存在于较浅深度时。

IDA*

将迭代加深的深度用 A* 的估价函数表示。

相较于 A* 的优势是更好写,且答案层数小的时候飞快。

例题 1

一个显然的想法是设 \(h_i\) 为当前局面每个点到目标的曼哈顿距离。

容易证明 \(h_i\le d_i\)

例题 2

\(h_i\) 表示有几个骑士该动。

posted @ 2025-04-22 19:39  一念行空  阅读(15)  评论(0)    收藏  举报