狀態壓縮DP (poj 3254, poj 1185, nyoj 81)

狀態壓縮DP, 一上來就卡了我好久。。。。。

poj3254應該是狀態壓縮裏最經典(簡單)得了吧

大意:就是在一塊地圖裏種草, 左右不能相鄰,上下也不能相鄰,  問一共有多少種種法(什麼不種也算一種)。

分析:M(<=12)行N(<=12)列的農場。很明顯的的壓縮DP,可以將其用二進制記錄,以十進制的形式存在數組裏。每一行最多12列(12個位置)所以int型足夠用了。

 d[i][j] = d[i][j] + d[i-1][k] (0 <= k <= N)

dp[i][j]代表第i行的第j中狀態一個出現的方案個數,對於j的狀態,要判斷是否可以存在,並且是否有兩個草地相鄰(即代碼中can()函數),並且還要判斷j狀態是否和第i-1行的的k狀態的草地相鄰,如果相鄰的話就捨棄!

見代碼吧!

可能上面那個是最簡單的壓縮DP了,做完這個我緊接着做了nyoj81,各種超內存啊!!

nyoj81 (和poj1185幾乎一樣)

描述
司令部的將軍們打算在N*M的網格地圖上部署他們的炮兵部隊。一個N*M的地圖由N行M列組成,地圖的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下圖。在每一格平原地形上最多可以佈置一支炮兵部隊(山地上不能夠部署炮兵部隊);一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所示:

如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,則圖中的黑色的網格表示它能夠攻擊到的區域:沿橫向左右各兩格,沿縱向上下各兩格。圖上其它白色網格均攻擊不到。從圖上可見炮兵的攻擊範圍不受地形的影響。
現在,將軍們規劃如何部署炮兵部隊,在防止誤傷的前提下(保證任何兩支炮兵部隊之間不能互相攻擊,即任何一支炮兵部隊都不在其他支炮兵部隊的攻擊範圍內),在整個地圖區域內最多能夠擺放多少我軍的炮兵部隊。
輸入
第一行輸出數據測試組數X(0<X<100)
接下來每組測試數據的第一行包含兩個由空格分割開的正整數,分別表示N和M; 接下來的N行,每一行含有連續的M個字符('P'或者'H'),中間沒有空格。按順序表示地圖中每一行的數據。0<=N <= 100;0<=M <= 10。
輸出
每組測試數據輸出僅一行,包含一個整數K,表示最多能擺放的炮兵部隊的數量。
樣例輸入
1
5 4
PHPP
PPHH
PPPP
PHPP
PHHP
樣例輸出
6
分析:首先這回求得是:最多能擺放的炮兵部隊的數量, 不再求總的方法個數了。
1.地圖轉換成一個二進制的數組(a[]),即一個整數表示一行的地形(1表示高地,0表示平原)。

        2.方程先上吧: d[i][j][k] = max(d[i][j][k], d[i-1][k][z] + number(row[j])); d[i][j][k]表示前i行, 第i行狀態爲j, i-1 行狀態爲k時的最多擺放數。row[j]是i行的某種狀態,number(x)功能:返回x用二進制表示時1的個數。

       3.應爲攻擊範圍沿橫向左右各兩格,沿縱向上下各兩格,所以再求每一行時應該前兩行的狀態都考慮。 相鄰三行不能衝突。首先,對行的遍歷,然後對當前行的狀態遍歷,然後對上一行的狀態遍歷,再對上上行的狀態遍歷,
這個方程就是遍歷上一行狀態爲k和上上行狀態爲z時的部署數量,求出最大部署數,再加上本行即i行,j狀態的部署(number(row[j]))。

      4.當時一看0<=M<=10,覺得很明朗啊,。。。可是一個三維數組d[100][2^10][2^10]太大了,各種超啊。。。看了大神的分析,才恍然大悟。。。。。從題中可分析每行中每兩個部署位置中間至少個兩個位置,所以我們可以預先判斷一下哪些情況纔是滿足的。其實滿足的情況只有60種,我們可以將這些滿足的狀態預先處理好存在row[]數組中。這樣三維數組就可以變成d[100][60][60]。這就不超了!!

        代碼:


額。。。。我這表達可能有點。。。。謝謝!!

發佈了32 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章