狀態壓縮動態規劃和狀態機動態規劃(未更新)大體上來說都是通過另類的方式來儲存動態規劃中的狀態。狀壓dp其實可以分為「棋盤式」和「集合類」,這篇是「棋盤式」或者叫「基於聯通性」的狀壓dp的一道經典例題——炮兵陣地的部落格。
炮兵陣地這道非常經典的狀態壓縮dp題目是值得學習的,可以從中學習到「棋盤式」狀壓dp的一些基本操作和標準化思想。
題目:
司令部的將軍們打算在 n∗m
n*mn∗
m 的網格地圖上部署他們的炮兵部隊。乙個 n∗m
n*mn∗
m 的地圖由n
nn行 m
mm 列組成,地圖的每一格可能是山地(用」h」 表示),也可能是平原(用」p」表示),如下圖。
在每一格平原地形上最多可以布置一支炮兵部隊(山地上不能夠部署炮兵部隊);一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所示:
如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,則圖中的黑色的網格表示它能夠攻擊到的區域:沿橫向左右各兩格,沿縱向上下各兩格。
圖上其它白色網格均攻擊不到。
從圖上可見炮兵的攻擊範圍不受地形的影響。
現在,將軍們規劃如何部署炮兵部隊,在防止誤傷的前提下(保證任何兩支炮兵部隊之間不能互相攻擊,即任何一支炮兵部隊都不在其他支炮兵部隊的攻擊範圍內),在整個地圖區域內最多能夠擺放多少我軍的炮兵部隊。
動規做法:
1、狀態表示:f[i
][j]
[k]f[i][j][k]
f[i][j
][k]
表示在更新第 i
ii 行時第 i−1
i-1i−
1 和 i−2
i-2i−
2 行的狀態分別為 j、k
j、kj、
k 的炮兵數量
這裡 j
jj 和 k
kk 是乙個數字,在二進位制下表示下1代表這裡可以放,而0是不能放(因為受上面的炮影響)。
2、狀態轉移:從第一行向下遞推
f [i
][j]
[k]=
maxf[i][j][k]=max\
f[i][j
][k]
=max
j
jj 表示第 i−1
i-1i−
1 行的狀態,k
kk 表示第 i−2
i-2i−
2 行的狀態,p
pp 表示第 i−3
i-3i−
3 行的狀態,cou
nt(j
)count(j)
count(
j)表示狀態 j
jj 中又多少個1。
當然,這裡的狀態轉移重要的是「合法」二字,對於「合法」要從兩個方面入手:
1)要從合法的狀態轉移到合法的狀態,對於單行狀態合法性的判斷就是要求兩個1之間至少隔兩個0:
bool
check
(int x)
2)就是轉移規則要合法,這一點有兩點限制:
a)地形要合法(這裡為了方便位運算,地形的儲存數字可以放是0,不可以是1)
b)該排的炮兵不能在前兩排的範圍內
if
(ori[i]
&a | ori[i-1]
&b)continue;if
((a&c)
|(a&b)
|(b&c)
)continue
;
最後在第 i
ii 行的所有合法狀態中找最大值即可。
注意,由於資料範圍,這裡 f
ff 陣列需要用滾動陣列儲存。
完整**:
#include
#include
#include
#include
using
namespace std;
const
int n=
110,m=
1<<10;
int f[2]
[m][m]
;vector<
int> state;
int cnt[m]
,ori[n]
;int n,m;
bool
check
(int x)
intcount
(int x)
intmain()
//cout
for(
int i=
0;i<
1<
(check
(i))
//ori[0]=(1
(int i=
1;i<=n;i++)}
}}int res=0;
for(
int i=
0;isize()
;i++
)for
(int j=
0;jsize()
;j++
) res=
max(res,f[n&1]
[state[i]
][state[j]])
; cout<
return0;
}
炮兵陣地(狀壓dp)
傳送門 poj 1185 司令部的將軍們打算在nm的網格地圖上部署他們的炮兵部隊。乙個nm的地圖由n行m列組成,地圖的每一格可能是山地 用 h 表示 也可能是平原 用 p 表示 如下圖。在每一格平原地形上最多可以布置一支炮兵部隊 山地上不能夠部署炮兵部隊 一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域...
狀壓DP之炮兵陣地
原題來自 noi 2001 司令部的將軍們打算在 n m 的網格地圖上部署他們的炮兵部隊。乙個 n m 的地圖由 n 行 m 列組成,地圖的每一格可能是山地 用 h表示 也可能是平原 用 p 表示 在每一格平原地形上最多可以布置一支炮兵部隊 山地上不能夠部署炮兵部隊 如果在地圖中的灰色所標識的平原上...
炮兵陣地 POJ 1185 狀壓dp
參考還是只能看別人的,他這裡預處理。所以存的就不是 1 10 那麼大的數了,所以可以儲存上乙個的狀態和這乙個的狀態。自己太粗心了。弄了挺久都沒改出來。以後再改吧。int n,m vectorstate 110 int dp 110 n n char s 110 15 void solve if i ...