狀態壓縮DP總結

2021-08-21 01:22:51 字數 1133 閱讀 2710

參考部落格:

狀態壓縮主要指的是用位運算代替列舉壓縮dp的時間,如果某乙個狀態和之前狀態的順序沒有關係,那麼就可以將之前的選或者不選壓縮到乙個二進位制數中。在選擇第i個時列舉之前的所有可能的i-1狀態,但是這i-1狀態是不記錄順序的,只在i-1到i時考慮順序,這樣的話往往能夠節約很多時間。

大致題意是從原點出發送披薩到n個點,給了pi直接到pj的時間,求送一遍再回到原點的最短時間(每個點可以走無數次)。但是有可能繞一段路比直接去時間更短,這就需要預處理一下找到pi到pj的最短時間,因為點的個數比較少所以o(n^3)也不會超時。具體的**沒有寫過,看了一下題目和題解,覺得這題還是挺經典的。想法很簡單,每乙個子狀態就是現在所在的點和之前到過的點,用乙個二進位制數來表示,然後列舉在這個點之前最後到的是哪乙個點,求出最短的時間。然後一些位運算的小技巧也是需要注意的:dp[s][i] =min(dp[s^(1<<(i-1))][j] + dis[j][i],dp[s][i]);用異或來表示除了i沒有走過其他都和s相同的狀態。

這題和上一題最大的不同在於每個點最多隻可以走兩遍。很自然地想到要用三進製數來壓縮狀態。不過三進製數好像沒有直接的位運算,所以得自己寫。然後看了一下大佬的**學習了一下怎麼寫三進製的dp優化。算乙個十進位制表示的k進製數的每一位是多少就是不斷把這個數%k然後/=k就可以了。把乙個三進製數的每一位都記下來,然後和之前一樣做就好了,判斷不能走的條件是某一位不能是2可以是1。不過三進製這種自己寫的顯然要比位運算慢很多,但是題目資料很小,只有10所以還是能過的。

題目大意是每乙個點都有權值vi,尋找一條漢密爾頓迴路使得權值最大,計算方法是把迴路中每個點的權值相加,再把走的相鄰兩點的權值之積相加,最後如果路徑上相鄰的三個點pi-2,pi-1,pi使得pi-2與pi-1之間有路徑相連(可以構成三角形)就把所有滿足條件的這三個點權值之積做和,三部分和相加得到最後的得分。這題其實細想並不難,基本思路也是一樣,只不過這回i的權值是和前兩個點有關的,這個意思就是狀態要記錄s,i,i-1開乙個三位陣列,轉移的時候算一下得分就好了。

#include#includelong long f[30][1<<12],i,j,height,width,saya=1;

void sayatime (int i,int s1,int pos)

sayatime(i,s1,pos+1);

if (pos<=width-2&&!(s1&1<

狀態壓縮dp總結 長期更新

狀壓dp本人做的題目真的不太多.至今還未理解到其中的精髓.所以以下的思路 描述中有存在不當的地方希望能夠指出.另外,有些地方說的比較複雜,因為本弱雞 對這些東西不是很理解.多寫點有助於理解吧.poj 1185 經典狀壓dp 我隊友這篇博文還不錯.思路 首先,我們可以發現對於每一行的當前位置能不能放炮...

狀壓dp(總結)狀態壓縮

狀壓這個和二進位制分不開關係 所以,對於二進位制的熟悉是必不可少的技能 與操作,1不變,0變0 或操作,0不變,1變1 異或操作,0不變,1取反 取反操作,把每乙個二進位制位0變1,1變0 還有一些複雜操作可以根據這些去理解 狀態壓縮 所謂狀態壓縮就是把dp的每一次轉移時的狀態用二進位制來表示 或者...

狀態壓縮DP

首先,我們以一道狀壓經典題tsp來引入。tsp問題 一張圖上有n個點,給定相應的鄰接矩陣,需要求出從0號節點出發,經過且只經過每個頂點一次,最後仍回到0號節點的最小邊權。思路 假設現在已訪問過的頂點集合 起點0當作還未訪問過的頂點 為s,當前所在頂點為v,用dp s v 表示從v出發訪問剩餘的所有頂...