1. 程式人生 > 其它 >插頭dp 筆記

插頭dp 筆記

插頭dp 筆記

限於我的水平,我們暫時只討論“簡單路徑問題”,並且例題不多

基礎知識

這個東西的全稱是 “基於連通性的狀態壓縮dp”。cdq有一篇論文講這個,是2008年的論文。

顧名思義,它乾的事情其實是,把“連通性”這個東西給壓縮起來了,並用這個壓縮方式,做一個dp。

插頭是啥

我們想要解決選路徑的問題。考慮現在有一個圖,現在加進來一個點,這個新點和原來的點有一些邊。

那選擇的路徑會發生怎麼樣的變化呢?對於原來的點,如果它已經有 \(2\) 的度數,那它就已經在路徑上,不能接更多的點了。而那些度數為 \(1\) 的點,就可以在邊上接一個點,這就是一個 “插頭”

怎麼壓縮連通性

對於一般圖,顯然,我們可以給一個連通塊標一個號。但是標號的方法有很多,我們需要找一種可以唯一確定,並且高效的記狀態的方法。

這很好搞,我們for一遍當前的點,碰到一個沒標號的,就 ++tot。容易發現這樣標的方法顯然唯一,並且 tot 恰好等於連通塊數。標號完之後雜湊一波就行了。複雜度是 O(劃分數)。如果要求準確,使用map的話,可能要多個log。

有一類特殊問題:要求在網格圖上搞一條路徑,穿過整個網格。比如說,一條哈密頓路。

這個問題有著一個特殊性,就是我們只需要記一條輪廓線的 \(m+1\) 個插頭,就可以轉移。如下圖,每次我們討論一下這條輪廓線“折角”的那個位置的兩個頭怎麼變化就行了。

考慮這條輪廓線上的插頭的連通性,發現它一定是兩兩配對,並且不相交的,像括號匹配一樣。

為什麼?考慮一條穿過整個網格的路徑,它肯定會跨過輪廓線,偶數次。一頭進,一頭出,那麼這兩個點的連通性就是匹配的。

不相交這個性質,想象一下就知道了,因為相交就會有度數 \(>2\) 的點。

我們可以把它的狀態壓縮成:\(0/1/2\)。對於那些配對的點,我們令左邊那個是 \(1\),右邊那個是 \(2\),就像括號匹配一樣。對於沒有插頭的那些位置,我們給他一個 \(0\)

比如上面那個圖,假設內部的連線情況如黃線所示,我們就給它一個 \(1,0,0,2,1,0,0,2\) 的狀態。

這可以用三進位制存,狀態數的數量是 \(O(3^{m+1})\)

來個例題

1 Ural 1519 Formula 1 / HNOI2004郵遞員

哈密頓迴路計數。\(n,m\le 12\)。有障礙。(HNOI那個題沒有,不影響本質)

考慮每個格子,四個方向的連線情況,相當於在下面的 \(6\) 個東西里面選一個

相當於在 \(4\) 個方向裡選兩個,\({4\choose 2}=6\)

狀態的表示已經整好了,考慮如何轉移。

影響轉移的只有“折角”的那兩個格子。討論它們插頭有無的情況。

設這兩個格子的狀態是 \(p,q\)\(p\) 在左,\(q\) 在右。

1. 都沒有,p=q=0

那往左,往上的插頭都不行,就只能有一種情況,就是往右、下的插頭。

然後我們需要把這兩個位置的狀態從原來的 \(p=0,q=0\) 變成 \(p=1,q=2\) ,因為這兩個插頭正好匹配

2. 其中一個有, pq=0, p+q>0

此時 \(p+q\)\(p,q\) 中非 \(0\) 的那個

那我們的其中一根插頭,肯定在左、上裡面選,並且得選有插頭的那一個。另一根插頭,在右、下里面選。

轉移到的狀態肯定其中一個是 \(0\),另一個是 \(p+q\)

有兩種,變成 \(0,p+q\)\(p+q,0\)

3. 倆都有

最複雜的情況,此時我們還需要討論

3.1 兩個左/右括號,p=q=1/2

首先是 \(p,q\) 這兩個位置被合併,都變成 \(0\)

其實是,原來和 \(p,q\) 匹配的那兩個位置,現在也匹配上了,我們依次給它 \(1,2\)

3.2 右+左,p=2,q=1

原來 \(p,q\) 匹配的兩個位置,現在匹配上了,\(p,q\) 變成 \(0\)

\(1,2,1,2\) 變成 \(1,0,0,2\)。我們發現,只需要改 \(p,q\) 倆位置,原來那些就自動匹配上了,根據括號序列的性質。

3.3 左+右,p=1,q=2

此時連線上 \(p,q\),就會有一個環出來。

而我們哈密頓路要求只有一個環,那一定是做到了最後一個格子,並且除了 \(p,q\) 位置都是 \(0\)。那此時會連出來恰好一個環。

這個情況直接轉移給答案就行了。

完畢。

此時把程式碼寫出來,發現就按這個討論的思路把程式碼實現了就行。(為啥有這麼毒瘤的討論,因為它本來就有這麼毒瘤的討論)

不是我對著程式碼在瞎講,是這程式碼就得對著討論寫

注意到兩個細節:

  • 換行,此時必須行末沒有插頭才行。然後我們可以把這個空插頭,移到最前面,以方便下一行的轉移
  • 障礙,這要求折角的兩個位置 \(p,q\) 都是 \(0\),並轉移到 \(0,0\) 的狀態

並小心另一個細節:當上面的兩個細節 同時出現 的時候。

(我就因為這個WA了好久)

程式碼

(這是ural那個題的程式碼,HNOI那個題的程式碼要小小的寫個高精)

怎麼只有一個題啊

會整的會整的,會有更多的qaq