1. 程式人生 > 其它 >狀態壓縮動態規劃【DP】

狀態壓縮動態規劃【DP】

一、概述

1.狀態壓縮
狀態壓縮就是使用某種方法,簡明扼要地以最小代價來表示某種狀態,通常是用一串01數字(二進位制數)來表示各個點的狀態。這就要求使用狀態壓縮的物件的點的狀態必須只有兩種,0 或 1;當然如果有三種狀態用三進位制來表示也未嘗不可。

2.使用條件
從狀態壓縮的特點來看,這個演算法適用的題目符合以下的條件:

解法需要儲存一定的狀態資料(表示一種狀態的一個數據值),每個狀態資料通常情況下是可以通過2進位制來表示的。這就要求狀態資料的每個單元只有兩種狀態,比如說棋盤上的格子,放棋子或者不放,或者是硬幣的正反兩面。這樣用0或者1來表示狀態資料的每個單元,而整個狀態資料就是一個一串0和1組成的二進位制數。
解法需要將狀態資料實現為一個基本資料型別,比如int,long等等,即所謂的狀態壓縮。狀態壓縮的目的一方面是縮小了資料儲存的空間,另一方面是在狀態對比和狀態整體處理時能夠提高效率。這樣就要求狀態資料中的單元個數不能太大,比如用int來表示一個狀態的時候,狀態的單元個數不能超過32(32位的機器),所以題目一般都是至少有一維的資料範圍很小。
3.狀壓DP
狀壓DP,顧名思義,就是使用狀態壓縮的動態規劃。

動態規劃問題通常有兩種,一種是對遞迴問題的記憶化求解,另一種是把大問題看作是多階段的決策求解。這裡用的便是後一種,這帶來一個需求,即儲存之前的狀態,再由狀態及狀態對應的值推演出狀態轉移方程最終得到最優解。

二、位運算

一般基礎的狀壓就是將一行的狀態壓成一個數,這個數的二進位制形式反映了這一行的情況。由於使用二進位制數來儲存被壓縮的狀態,所以要用到神奇的二進位制位運算操作,將一個十進位制數轉成二進位制進行位運算操作再轉回十進位制數。

名稱 運算子 Pascal樣式 簡記法則
按位與 & and 全一為一,否則為零
按位或 | or 有一位一,否則為零
按位取反 ~ not 是零則一,是一則零
按位異或 ^ xor 不同則一,相同則零
左移位 << shl a<<k等價於a*2^k
右移位 >> shr a>>k等價於a/2^k

注:在涉及到位運算時,一定要注意位運算的優先順序。該加的括號一定要加

定義狀態(例如) 求每一種放法的揹包價值,狀態應該是這n件物品的放與不放的情況。

最容易想到的是開個n維陣列,第i個維度的下標如果是1的話代表放第i件物品,0的話代表不放第i件物品;

但是這樣很容易造成空間浪費,而且多維陣列也不好開;

我們仔細觀察就會發現,每件物品有放與不放兩種選擇;假設我們有5件物品的時候,用1和0代表放和不放

如果這5件物品都不放的話,那就是00000;
如果這5件物品都放的話, 那就是11111;

看到這,我們知道可以用二進位制表示所有物品的放與不放的情況;如果這些二進位制用十進位制表示的話就只有一個維度了。而且這一個維度能表示所有物品放與不放的情況;這個過程就叫做狀態壓縮;

注:先簡單寫一下 回頭再改一下