插头DP/轮廓线DP

题解 P5056 【【模板】插头dp】- GNAQ

\(\uparrow\) 学习资料,大部分贺的,有一些些的改动与自己的补充)

什么是插头 DP

插头 DP 是一类用状压 DP 来处理连通性问题的 DP 方法。

常见的类型:棋盘插头 DP、连通性问题(回路问题,路径问题,生成树问题等)……

插头 DP 的大致思路

划分状态

插头 DP 本质上式状压 DP!

一般设 \(dp(i,state,\dots)\) 表示在位置 \(i\),状态为 \(state\) 的方案。

状态 \(state\) 是求解的轮廓线,就是一个将已经做出决策的点与没有做出决策的分割线。

在棋盘问题中,我们选择逐格转移,因此轮廓线就是上面以及覆盖的棋盘与下面没有覆盖的棋盘的分割线。

那么插头又是什么呢?一个格子和周围四个格子有相接,那么这个各自就有四个可能的插头。插头表示两个格子之间的联通情况。

记录状态

最小表示法

???还不是很懂,大概是一个连通块一个连通块标记??

括号表示法

将插头之间的联通情况的联通情况用括号表示,两个联通的插头左边的表示为 \((\),右边的表示为 \()\),没有的表示 \(\#\)

之后用 \(0\) 表示 \(\#\),用 \(1\) 表示 \((\),用 \(2\) 表示 \()\)

状态的编码

最简单的方法就是表示为一个 \(n+1\) 位的 \(p\) 进制,用进制上的加减压缩。

最好的方式是将 \(p\) 变为 \(2\) 的幂次,如二进制、四进制等。可以将三进制用四进制表示等等。

转移状态

我们的目标通常是用一定表示方法将这根轮廓线表示出来并且分类讨论实现各种转移。

一般来说,转移可以:

  1. 新建一个状态。

  2. 合并一个状态。

  3. 保持原来的状态,即移动一个状态。

\(\bigstar\texttt{important}\):记得在转移的时候判断是否到达一个合法的状态!!记得在取出一个状态的时候判断这个状态是否合法!!!

状态记录的优化

有时候发现状态超级大,无法记录怎么办?而 map 实在是太慢啦!

那就用哈希表吧!

即,我们将状态根据一个随机的模数分为很多种类,分别建立链表挂链表打查询。

访问状态的时候可以直接根据链式前向星直接拉出所有合法状态,转移的时候可以高效加入。

例题

P5056 【模板】插头dp

模板题!(但只是插头DP的入门题)

记得在转移的时候判断这个转移的合法性!!比如这个轮廓线能不能向右走、向下走(是不是墙)。

再一次拉出来的时候还要再判断一次。

几乎一模一样:P3190 [HNOI2007]神奇游乐园

P3272 [SCOI2011]地板

这里假设状态中这一位为 \(1\) 表示这个插头指向的格子为 L 形的一只手,另一只手已经完成,下一位必选;\(2\) 表示插头指向的格子为 L 形的第一只手,需要转弯。

这样继续四进制转移即可。

posted @ 2022-02-07 21:02  EricQian06  阅读(297)  评论(0编辑  收藏  举报