POJ 1185 炮兵陣地 狀壓dp

2021-07-26 18:47:42 字數 1928 閱讀 2344

炮兵陣地

time limit:2000ms

memory limit:65536k

total submissions:26819

accepted:10362

description

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

如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,則圖中的黑色的網格表示它能夠攻擊到的區域:沿橫向左右各兩格,沿縱向上下各兩格。圖上其它白色網格均攻擊不到。從圖上可見炮兵的攻擊範圍不受地形的影響。 

現在,將軍們規劃如何部署炮兵部隊,在防止誤傷的前提下(保證任何兩支炮兵部隊之間不能互相攻擊,即任何一支炮兵部隊都不在其他支炮兵部隊的攻擊範圍內),在整個地圖區域內最多能夠擺放多少我軍的炮兵部隊。 

input

第一行包含兩個由空格分割開的正整數,分別表示n和m; 

接下來的n行,每一行含有連續的m個字元('p'或者'h'),中間沒有空格。按順序表示地圖中每一行的資料。n <= 100;m <= 10。

output

僅一行,包含乙個整數k,表示最多能擺放的炮兵部隊的數量。

sample input

5 4

phpp

pphh

pppp

phpp

phhp

sample output

6
source

noi 01

狀態壓縮的很巧妙,把每個點上放和不放看為1和0 ,這樣就可以把一行上放與不放的狀態視為乙個二進位制數,同樣也對應了乙個十進位制數,例如只有第乙個點放1000   對應了8

又因為炮的**範圍是二,這一行的狀態只和前兩行有關,並且判定這兩行的狀態能不能同時存在,把這兩個數&一下,因為對應位不能同時為一,也就是不能都放炮兵

先把所有能存在的狀態找出來,也就是這個數的位上不能存在相鄰或兩個間隔只有一的兩個1

dp【i】【j】【k】代表第i行是j狀態,第i-1行是k狀態時最多能放的炮兵數量,

然後對於每一行求解,都列舉包括此行在內在加上前兩行所有的狀態,找到可以同時存在的那個情況,dp【i】【j】【k】=max(dp【i】【j】【k】,dp【i-1】【k】【z】)

儲存兩個狀態是因為確定當前狀態是否可行必須要知道前兩個狀態,那麼如何做到遞推方程裡只有這三個狀態呢,那就只能是dp陣列裡儲存兩個狀態,當前狀態和前乙個狀態

#include#include#include#include#include#include#include#include#include#define legal(a,b) a&b 

typedef long long ll;

using namespace std;

int dp[150][70][70],n,m,base[150],state[70],sn[70];

int get(int x)

return s;

}int main()

}for(num=0,i=0;i

//printf("%d\n",num);

for(i=0;i

for(i=0;i

}for(i=2;i}}

}ans=0;

for(i=0;i

}printf("%d\n",ans);

return 0;

}

POJ1185(炮兵陣地) 狀壓DP

每一行的狀態是取決於上一行和上上一行的,所以每次更新的時候需要記錄當前行的狀態和下一行的狀態,然後再進行遞推。不過估算了一下複雜度是10的11次方,嚇得我都沒敢寫啊!看了一下別人的部落格,居然真有這樣寫過的,於是就自己實現一邊啦 最後看了以下討論版,處理一下複雜度可以降低的,最後貼討論版 思路 令p...

POJ1185 炮兵陣地 狀壓dp

司令部的將軍們打算在n m的網格地圖上部署他們的炮兵部隊。乙個n m的地圖由n行m列組成,地圖的每一格可能是山地 用 h 表示 也可能是平原 用 p 表示 如下圖。在每一格平原地形上最多可以布置一支炮兵部隊 山地上不能夠部署炮兵部隊 一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所示 如果在地圖中的灰...

POJ 1185 炮兵陣地 狀壓DP

炮兵陣地 time limit 2000ms memory limit 65536k total submissions 25954 accepted 10004 description 司令部的將軍們打算在n m的網格地圖上部署他們的炮兵部隊。乙個n m的地圖由n行m列組成,地圖的每一格可能是山地...