狀壓DP之炮兵陣地

2022-01-30 14:25:17 字數 1393 閱讀 4534

原題來自:\(noi 2001\)

司令部的將軍們打算在\(n*m\)

的網格地圖上部署他們的炮兵部隊。乙個\(n*m\)的地圖由\(n\)行\(m\)列組成,地圖的每一格可能是山地(用 h表示),也可能是平原(用 p 表示)。在每一格平原地形上最多可以布置一支炮兵部隊(山地上不能夠部署炮兵部隊),如果在地圖中的灰色所標識的平原上部署一支炮兵部隊,它能夠攻擊到的區域:沿橫向左右各兩格,沿縱向上下各兩格。其他位置攻擊不到。炮兵的攻擊範圍不受地形的影響。現在,將軍們規劃如何部署炮兵部隊,在防止誤傷的前提下(保證任何兩支炮兵部隊之間不能互相攻擊,即任何一支炮兵部隊都不在其他支炮兵部隊的攻擊範圍內),在整個地圖區域內最多能夠擺放多少我軍的炮兵部隊。

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

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

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

5 4phpp

pphh

pppp

phpp

phhp

這道題是乙個很有趣的狀壓dp,由題意可知,對當前狀態影響的有當前行狀態,上一行狀態,以及上上行的狀態,對該行都有影響,所以,很顯然我們列舉第\(i\)行,\(i-1\)行以及\(i-2\)的狀態,對於任意一行(假設為\(i\)),那麼我們對第\(i\)行進行合法化判斷(僅對當前行),記錄合法狀態以及數目,方便下面列舉,還需要注意的是地圖上的山地,需要單獨開乙個陣列記錄,與列舉狀態求&,然後我們設\(f\)的三維陣列,即\(f[i][j][k]\)代表第i行第j種狀態從上一行第k種狀態轉移過來的最優解,所以有\(f[i][w][k]=max(f[i][w][k],f[i-1][k][j]+q(w))\),\(f[i][w][k]\)上一狀態為\(f[i-1][k][j]\),繼承或求較大值更新

#includeusing namespace std;

const int maxn=1<<9;

int f[100+10][maxn][maxn];//第i行第j種狀態從上一行第k種狀態轉移過來的最優解

int a[100+10];//記錄地圖山丘的數量

int state[maxn];//記錄合法的狀態

int tot,n,m;

int lowbit(int x)

int q(int x)

bool judge(int x)

int main()

} for(int i=0;i<(1

for(int i=2;i<=n;i++)

}} }

int ans=0;

for(int i=1;i<=tot;i++)

} cout<}

炮兵陣地(狀壓dp)

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

DP 狀壓 DP 炮兵陣地

狀態壓縮動態規劃和狀態機動態規劃 未更新 大體上來說都是通過另類的方式來儲存動態規劃中的狀態。狀壓dp其實可以分為 棋盤式 和 集合類 這篇是 棋盤式 或者叫 基於聯通性 的狀壓dp的一道經典例題 炮兵陣地的部落格。炮兵陣地這道非常經典的狀態壓縮dp題目是值得學習的,可以從中學習到 棋盤式 狀壓dp...

炮兵陣地 POJ 1185 狀壓dp

參考還是只能看別人的,他這裡預處理。所以存的就不是 1 10 那麼大的數了,所以可以儲存上乙個的狀態和這乙個的狀態。自己太粗心了。弄了挺久都沒改出來。以後再改吧。int n,m vectorstate 110 int dp 110 n n char s 110 15 void solve if i ...