DP 狀壓 DP 炮兵陣地

2021-10-02 21:40:43 字數 2824 閱讀 8270

狀態壓縮動態規劃和狀態機動態規劃(未更新)大體上來說都是通過另類的方式來儲存動態規劃中的狀態。狀壓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 ...