dp過程中的狀態不可能像揹包問題一樣只有整數,肯定有各種各樣稀奇古怪的狀態,需要不止乙個變數來表示。這種情況下如果需要使用dp 就必須把狀態壓縮成乙個數來表示,並且乙個數只能對應於一種狀態。
特別地,對於集合我們可以把每乙個元素的選取與否對應到乙個二進位制位裡,從而把狀態壓縮成乙個整數,大大方便了計算和維護。
對於不是整數的情況,很多時候很難確定乙個合適的遞推順序,因此使用記憶化搜尋可以避免這個問題。如下面tsp問題的法一。
一張圖上有n個點,給定相應的鄰接矩陣,需要求出從0號節點出發,經過且只經過每個頂點一次,最後仍回到0號節點的最小邊權。tsp問題可以用狀壓dp來快速求解。
定義dp[s][v]為已經經過了點集s之後,目前在點v(v已經包含在s中),回到0節點的最小邊權。
所以有如下的遞推公式
**dp[v[0] = 0
dp[s][v] = min(dp[s∪][u]+d[v][u])(其中u不屬於s)**
將s看作乙個長度為n的bit流,第幾號節點訪問過就把s的第幾號節點置為1,其他都是0,這樣就可以將狀態壓縮成了乙個數字來表示,並且有一一對應性。
採用記憶化搜尋的tsp狀壓dp**如下
int n;
int d[maxn][maxn];
int dp[1<][maxn];
int rec(int s,int v)
if(v == 0 && s == (1for(int i = 0 ; i < n ; i ++)
}return dp[s][v] = ans;
}void solve(void)
此外也可以不用記憶化搜尋,觀察遞推的順序從而使用迴圈求解。
發現對於任意的兩個整數i和j 如果它們對應的集合滿足s(i)包含於s(j) 那麼i<=j。**如下
int dp[1
狀態壓縮 TSP問題
有乙個n m的矩陣上存在一些石頭,接下來要從起點出發把這些石頭拿上並回到起點,問最小需要多少步。用sum表示除了 1,1 這個點外其他有石頭的點的個數,用x陣列和y陣列表示這些點的座標的位置,在這裡我用二進位制下的每個位置表示點的位置,將最後的位置來表示起點,0 n 1分別表示其他點的位置,然後開始...
poj 2688 狀態壓縮dp解tsp
題意 裸的tsp。分析 用bfs求出任意兩點之間的距離後可以暴搜也可以用next permutation水,但效率肯定不如狀壓dp。dp s u 表示從0出發訪問過s集合中的點,目前在點u走過的最短路程。poj 2688 sep9 include include using namespace st...
狀態壓縮dp與樹形dp
狀態壓縮動態規劃 動態規劃的狀態有時候比較難,不容易表示出來,需要用一些編碼技術,把狀態壓縮的用簡單的方式表示出來。典型方式 當需要表示乙個集合有哪些元素時,往往利用2進製用乙個整數表示。一般有個資料 n 16 或者 n 32 這個很可能就是狀態dp的標誌,因為我們要用乙個int的二進位制來表示這些...