題目描述
司令部的將軍們打算在nm的網格地圖上部署他們的炮兵部隊。乙個nm的地圖由n行m列組成,地圖的每一格可能是山地(用「h」 表示),也可能是平原(用「p」表示),如下圖。在每一格平原地形上最多可以布置一支炮兵部隊(山地上不能夠部署炮兵部隊);一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所示:
如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,則圖中的黑色的網格表示它能夠攻擊到的區域:沿橫向左右各兩格,沿縱向上下各兩格。圖上其它白色網格均攻擊不到。從圖上可見炮兵的攻擊範圍不受地形的影響。 現在,將軍們規劃如何部署炮兵部隊,在防止誤傷的前提下(保證任何兩支炮兵部隊之間不能互相攻擊,即任何一支炮兵部隊都不在其他支炮兵部隊的攻擊範圍內),在整個地圖區域內最多能夠擺放多少我軍的炮兵部隊。
輸入格式
第一行包含兩個由空格分割開的正整數,分別表示n和m;
接下來的n行,每一行含有連續的m個字元(『p』或者『h』),中間沒有空格。按順序表示地圖中每一行的資料。n≤100;m≤10。
輸出格式
僅一行,包含乙個整數k,表示最多能擺放的炮兵部隊的數量。
輸入輸出樣例
輸入 #1
5 4
phpp
pphh
pppp
phpp
phhp
輸出 #16
解題思路
一開始把所有可能的狀態s[]
ss[
]求出來,c[]
cc[
]記錄每個狀態有多少1(放了多少個士兵)
設f []
[][]
ff[
][]存的是最多的士兵數
f [i
][k]
[j
]f[i][k][j]
f[i][k
][j]
為第i
ii行狀態為第j
jj種狀態,第i−1
i-1i−
1行的狀態為第k
kk種狀態(i
ii,j
jj,k
kk都要列舉)
由於兩個士兵必須隔兩格,所以還要列舉i−2
i-2i−
2行的狀態編號(lll)
f[i]
[k][j]
=max
(f[i]
[k][j]
, f[i-1]
[l][k]
+ c[j]
);
上一行的狀態編號是k,上一行中的f的上一行編號是l(上兩行)
code
#include
#include
using namespace std;
char read;
long long ans, f[
105]
[120][
120]
;int n, m, num, a[
150]
, s[
110]
, c[
110]
;int main()
}for
(int i =
0; i <(1
<; i++
)//列舉狀態
for(int i =
1; i <= num; i++
)for
(int j =
1; j <= num; j++)if
(!(a[2
]& s[j])&&
!(s[j]
& s[i]))
f[2]
[i][j]
= f[1]
[0][i]
+ c[j]
;//預處理第二行
for(int i =
3; i <= n; i++
)for
(int j =
1; j <= num; j++)}
}for
(int i =
1; i <= num; i++
)for
(int j =
1; j <= num; j++
) ans =
max(ans, f[n]
[i][j]);
printf
("%lld\n"
, ans)
;}
luogu2704 炮兵陣地 狀態壓縮DP
題目大意 乙個n m的地圖由n行m列組成,地圖的每一格可能是山地 用 h 表示 也可能是平原 用 p 表示 在每一格平原地形上最多可以布置一支炮兵部隊,能攻擊到的區域 沿橫向左右各兩格,沿縱向上下各兩格。保證任何兩支炮兵部隊之間不能互相攻擊時,最多能放置的炮兵數。n 100,n 10 動規先要確定方...
洛谷2704 狀壓dp
思路 這個狀壓確實挺強。第i行的不僅僅和i 1行有關係,還和i 2行有關係。一般的思路好像解決不了問題,咋搞?我們定義乙個陣列 dp 105 1 10 1 10 dp i t1 t2 i表示的是當前行,t1表示的是當前行的狀態,t2表示的是i 1行的狀態。假設t3表示的是i 2行的狀態,列舉i 2行...
DP 狀壓 DP 炮兵陣地
狀態壓縮動態規劃和狀態機動態規劃 未更新 大體上來說都是通過另類的方式來儲存動態規劃中的狀態。狀壓dp其實可以分為 棋盤式 和 集合類 這篇是 棋盤式 或者叫 基於聯通性 的狀壓dp的一道經典例題 炮兵陣地的部落格。炮兵陣地這道非常經典的狀態壓縮dp題目是值得學習的,可以從中學習到 棋盤式 狀壓dp...