題解 p5056 【【模板】插頭dp】- gnaq
(\(\uparrow\) 學習資料,大部分賀的,有一些些的改動與自己的補充)
插頭 dp 是一類用狀壓 dp 來處理連通性問題的 dp 方法。
常見的型別:棋盤插頭 dp、連通性問題(迴路問題,路徑問題,生成樹問題等)……
插頭 dp 本質上式狀壓 dp!
一般設 \(dp(i,state,\dots)\) 表示在位置 \(i\),狀態為 \(state\) 的方案。
狀態 \(state\) 是求解的輪廓線,就是乙個將已經做出決策的點與沒有做出決策的分割線。
在棋盤問題中,我們選擇逐格轉移,因此輪廓線就是上面以及覆蓋的棋盤與下面沒有覆蓋的棋盤的分割線。
那麼插頭又是什麼呢?乙個格仔和周圍四個格仔有相接,那麼這個各自就有四個可能的插頭。插頭表示兩個格仔之間的聯通情況。
最小表示法
???還不是很懂,大概是乙個連通塊乙個連通塊標記??
括號表示法
將插頭之間的聯通情況的聯通情況用括號表示,兩個聯通的插頭左邊的表示為 \((\),右邊的表示為 \()\),沒有的表示 \(\#\)。
之後用 \(0\) 表示 \(\#\),用 \(1\) 表示 \((\),用 \(2\) 表示 \()\)。
狀態的編碼
最簡單的方法就是表示為乙個 \(n+1\) 位的 \(p\) 進製,用進製上的加減壓縮。
最好的方式是將 \(p\) 變為 \(2\) 的冪次,如二進位制、**制等。可以將三進製用**制表示等等。
我們的目標通常是用一定表示方法將這根輪廓線表示出來並且分類討論實現各種轉移。
一般來說,轉移可以:
新建乙個狀態。
合併乙個狀態。
保持原來的狀態,即移動乙個狀態。
\(\bigstar\texttt\):記得在轉移的時候判斷是否到達乙個合法的狀態!!記得在取出乙個狀態的時候判斷這個狀態是否合法!!!
有時候發現狀態超級大,無法記錄怎麼辦?而map
實在是太慢啦!
那就用雜湊表吧!
即,我們將狀態根據乙個隨機的模數分為很多種類,分別建立鍊錶掛鍊錶打查詢。
訪問狀態的時候可以直接根據鏈式前向星直接拉出所有合法狀態,轉移的時候可以高效加入。
模板題!(但只是插頭dp的入門題)
記得在轉移的時候判斷這個轉移的合法性!!比如這個輪廓線能不能向右走、向下走(是不是牆)。
再一次拉出來的時候還要再判斷一次。
幾乎一模一樣:p3190 [hnoi2007]神奇遊樂園
這裡假設狀態中這一位為 \(1\) 表示這個插頭指向的格仔為l
形的乙隻手,另乙隻手已經完成,下一位必選;\(2\) 表示插頭指向的格仔為l
形的第一隻手,需要轉彎。
這樣繼續**制轉移即可。
輪廓線DP 專項
題意 n m n mn m n,m 11 的矩陣,填1 2 1 21 2或2 12 1 2 1方塊,求方案數 解析 以前寫過狀壓的做法,直接一行一行維護,現在寫輪廓線的做法 注意 當前填紅點的意思是,以紅點作為方塊的右下角 因為方塊長度為2,所以對紅點位置有三種操作 向上填 為了使所有方塊填滿,如果...
group 狀壓dp,輪廓線
神仙題。但是難得的傻孩子cbx沒有喊題解,所以也就難得的自己想出來了乙個如此神仙的題。如果是自己想的,說它神仙是不是有點不合適啊。反正的確不好像。關鍵就在於這個標籤。頹完標籤就差不多會了。cbx那麼快就想出來了。2個小時?廢話多了。先考慮暴力。對於16的資料範圍當然要考慮狀壓,狀態表示每乙個位置是否...
簡單的遊戲(10進製輪廓線dp)
題目 假設有5列,那麼每一列用乙個數來填充,最大是99999,最小是00000.由於m 6,所以最大狀態是999999,可以直接從0開始列舉,到999999複雜度為1e6。dp sta cur 表示當狀態為sta時的方案數,由於當前狀態由前乙個狀態轉移過來,所以cur只需要0或1就行。思路和普通的二...