模板:插頭dp

前言:

嚴格來說有關dp的都不該該叫作模板,由於dp太活了,可是一是爲了整理插頭dp的知識,二是插頭dp有良好的套路性,因此姑且還叫作模板吧。html

這裏先推薦一波CDQ的論文和這篇博客http://www.yhzq-blog.cc/%E6%8F%92%E5%A4%B4dp-%E4%BB%8E%E4%B8%8D%E4%BC%9A%E5%88%B0%E5%B4%A9%E6%BA%83/,下列一部分知識借鑑了他們的思想與內容。算法

————————————————————————post

問題引入:

URAL1519:Formula 1學習

題目大意:給一個網格,有些網格有障礙,問有多少條哈密頓迴路。優化

————————————————————————spa

概念引入:

插頭dp:基於連通性狀態壓縮的動態規劃。orm

插頭:(對於本問題而言)一個格子能夠與外面相連的邊,顯然一般是有上下左右四個插頭。htm

輪廓線:已決策格子和未決策格子的分界線。blog

性質:

對於輪廓線上從左到右的四個插頭abcd,若是a與c聯通,則b與d必定不連通。遊戲

(可感性理解,也可對照論文看證實,證實並不難)

————————————————————————

在講以前,我先闡述一下我對於插頭dp的理解模型:水管遊戲

(本文會使用水管遊戲的一些概念)

玩完了吧,是否是很好玩?好玩的話咱們就正式開始學習插頭dp吧。

(可是請注意一個水管只容許有兩個口,和遊戲中不同)

(好了不要玩遊戲了……)

————————————————————————

最小表示法:

首先定義連通性:若是兩個格子的水管是相接的,那麼稱這兩個格子是聯通的。多個聯通的格子組成了聯通塊。

這就給咱們一種表示輪廓線當前狀態的方法:f(i,j,S)表示逐格遞推到(i,j)格的時候咱們的狀態爲S,其中S中"0"表明無插頭,不然均有插頭,且數字相同的插頭聯通。

可是這樣很慢(S的進制不是很優,沒法常數優化,且可能形成多餘的狀態)

————————————————————————

括號表示法:

看一看那個結論,不以爲恨眼熟嗎?是否是和括號很像啊?

括號表示法就是這樣的方法:

咱們令

0=無插頭

1=左匹配插頭"("

2=右匹配插頭")"

(固然咱們爲了常數優化一般取四進制,這樣就能夠位運算了)

那麼顯然1與2配對的時候表明咱們查到了一個聯通塊,且不能出現([)]的狀況,因此這種表示方法獲得的狀態是惟一的。

它顯然比上一種方法(在常數上)更優,因此咱們能夠採用這種方法的話通常採用這種方法。

(至於獨立插頭……emm……網上沒有一我的寫過這個……)

————————————————————————

實現:

實現蠻好想的,具體的算法構架以下:

1.模擬輪廓線移動。

2.枚舉當前可能出現的全部狀態。

3.對於新更新的格子,合併/分離/維持聯通塊。

4.將新狀態更新爲括號表示/最小表示法,存儲。

存儲的方法使用哈希表便可。

其中最關鍵(也是最複雜)的地方爲3,可是因爲做者懶,因此請參考文章開頭提供的博客,那裏有圖文註釋,比較容易能看懂。

————————————————————————

總結:

其實插頭dp不難,可是在我想到用水管遊戲解釋插頭以前我確實是mengbier,因此說這個東西就是理解起來困難,理解了就真的不難了。

強烈推薦先抄一個代碼,大體實現一下插頭dp,感性理解有助於接下來的作題。

(好比個人代碼就是抄的那篇博客……)

例題:

最小表示法:

BZOJ2595:[Wc2008]遊覽計劃:http://www.cnblogs.com/luyouqi233/p/8258525.html

括號表示法:

URAL1519:Formula 1:http://www.cnblogs.com/luyouqi233/p/8256801.html

BZOJ1187:[HNOI2007]神奇遊樂園:http://www.cnblogs.com/luyouqi233/p/8260236.html

靈活運用:

BZOJ2331:[SCOI2011]地板:http://www.cnblogs.com/luyouqi233/p/8261279.html

相關文章
相關標籤/搜索