Loading docs/search/bidirectional.md +8 −8 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ author: FFjet, ChungZH, frank-xjh, hsfzLZH1, Xarfa, AndrewWayne 双向广搜的步骤: ```text 开始结点 和 目标结点 入队列 q 将开始结点和目标结点加入队列 q 标记开始结点为 1 标记目标结点为 2 while (队列 q 不为空) Loading Loading @@ -35,7 +35,7 @@ while(队列q不为空) $1\le n\le 35$ 。 如果这道题暴力 DFS 找开关灯的状态,时间复杂度就是 $O(2^{n})$ , 显然超时。不过,如果我们用 **meet-in-middle** 的话,时间复杂度可以优化至 $O(n2^{n/2})$ 。 **meet-in-middle** 就是让我们先找一半的状态,也就是找出只使用编号为 $1$ 到 $\mathrm{mid}$ 的开关能够到达的状态,再找出只使用另一半开关能到达的状态。如果前半段和后半段开启的灯互补,将这两段合并起来就得到了一种将所有灯打开的方案。具体实现时,可以把前半段的状态以及达到每种状态的最少按开关次数存储在 `map` 里面,搜索后半段时,每搜出一种方案,就把它与互补的第一段方案合并来更新答案。 如果这道题暴力 DFS 找开关灯的状态,时间复杂度就是 $O(2^{n})$ , 显然超时。不过,如果我们用 **meet-in-middle** 的话,时间复杂度可以优化至 $O(n2^{n/2})$ 。 **meet-in-middle** 就是让我们先找一半的状态,也就是找出只使用编号为 $1$ 到 $\mathrm{mid}$ 的开关能够到达的状态,再找出只使用另一半开关能到达的状态。如果前半段和后半段开启的灯互补,将这两段合并起来就得到了一种将所有灯打开的方案。具体实现时,可以把前半段的状态以及达到每种状态的最少按开关次数存储在 map 里面,搜索后半段时,每搜出一种方案,就把它与互补的第一段方案合并来更新答案。 ??? note "参考代码" ```cpp Loading Loading
docs/search/bidirectional.md +8 −8 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ author: FFjet, ChungZH, frank-xjh, hsfzLZH1, Xarfa, AndrewWayne 双向广搜的步骤: ```text 开始结点 和 目标结点 入队列 q 将开始结点和目标结点加入队列 q 标记开始结点为 1 标记目标结点为 2 while (队列 q 不为空) Loading Loading @@ -35,7 +35,7 @@ while(队列q不为空) $1\le n\le 35$ 。 如果这道题暴力 DFS 找开关灯的状态,时间复杂度就是 $O(2^{n})$ , 显然超时。不过,如果我们用 **meet-in-middle** 的话,时间复杂度可以优化至 $O(n2^{n/2})$ 。 **meet-in-middle** 就是让我们先找一半的状态,也就是找出只使用编号为 $1$ 到 $\mathrm{mid}$ 的开关能够到达的状态,再找出只使用另一半开关能到达的状态。如果前半段和后半段开启的灯互补,将这两段合并起来就得到了一种将所有灯打开的方案。具体实现时,可以把前半段的状态以及达到每种状态的最少按开关次数存储在 `map` 里面,搜索后半段时,每搜出一种方案,就把它与互补的第一段方案合并来更新答案。 如果这道题暴力 DFS 找开关灯的状态,时间复杂度就是 $O(2^{n})$ , 显然超时。不过,如果我们用 **meet-in-middle** 的话,时间复杂度可以优化至 $O(n2^{n/2})$ 。 **meet-in-middle** 就是让我们先找一半的状态,也就是找出只使用编号为 $1$ 到 $\mathrm{mid}$ 的开关能够到达的状态,再找出只使用另一半开关能到达的状态。如果前半段和后半段开启的灯互补,将这两段合并起来就得到了一种将所有灯打开的方案。具体实现时,可以把前半段的状态以及达到每种状态的最少按开关次数存储在 map 里面,搜索后半段时,每搜出一种方案,就把它与互补的第一段方案合并来更新答案。 ??? note "参考代码" ```cpp Loading