POJ 1185 炮兵陣地 狀態DP 經典題

2021-06-29 10:32:38 字數 1018 閱讀 7358

本題的難度給跪了,完全不是自己的能力範圍內,看了別人的解題報告才寫的

摘自題目大意

:給定一張n*m的地圖,地圖上有平原p,有山地h,可以在平原p**,俗稱野戰,**方向有四個,上下左右,射程是2,要求兩個炮不能相互打到,問符合這個要求的情況最多打幾個炮?n <= 100,m <= 10.

解題思路:

經典noi題,矩陣裡的狀態壓縮問題。

因為m<=10,而每列都有狀態選或不選,所以想到用2進製,那麼狀態數是2^10。因為當前行的選擇依賴於前兩行,而前一行又依賴於前前兩行,能想到狀態轉移方程應該牽扯到當前行、前一行、前前行

,類似於遞推式dp[i] = dp[i-1] + dp[i-2]的遞推過程,而本體每次都是狀態間的轉移,想到狀態轉移方程dp[i][j][k] = max(dp[i][k][l]) + sum[j](j和k和l表示當前行狀態,前一行狀態,前前行狀態,sum[j]表示j狀態下在i行放了幾個大炮)。

狀態數並不是dp[n][1<

//2140 kb 266 ms c++ 2456 b

#include#include#include#includeusing namespace std;

const int maxn = 110;

int state[maxn][maxn] ; //state[i][j]表示第i行第j個合法狀態

int ans, stnum[maxn], sum[2222]; //stnum[i]表示i行合法的狀態數,sum[i]為i狀態下1的個數

int n, m, map[maxn][maxn], dp[maxn][70][70]; //dp[i][j][k]表示第i行第j個狀態第-1行第k個狀態含有的最多1的個數

void stago(int x)

}void ini()

int main()

{ for(int i=0;i<(1<<10);i++)

{int s=0;

for(int j=0;j<10;j++)

if(i&(1<

POJ1185 炮兵陣地 狀態壓縮DP

感覺和3254很像,不過這次的間隔變成兩格,當前行的狀態與上兩行的狀態有關。狀態轉移方程 dp k q i max dp k q i dp q j i num k num k 表示狀態k的炮兵數量 dp k q i 表示當前第i行為狀態k上一行的狀態為q的炮兵數量總數。炮兵陣地 time limit...

poj 1185 炮兵陣地 狀態壓縮dp

之前想做黑書上的那個狀態壓縮dp,不會寫 退而求其次,寫了這個,也糾結也好久,其實只要想好,算好時間複雜度,大膽寫就好,想的時候總覺得這樣會超時,迴圈好多什麼什麼的,又懶得看解題報告,所以拖了好久 結果寫出來就a掉了,219ms dfs求出每一行的狀態,最多一行的狀態是60中,算不出的可以用10個p...

POJ 1185 炮兵陣地 (狀態壓縮dp)

原來寫過這篇博哦,超詳細誒。哈哈!再寫一遍,覺得比較重要和值得注意的兩點是 1 遞推時i行 i 1行 i 2行選擇狀態的三個for迴圈的巢狀順序。感覺順序好像沒什麼。我不知道為什麼第一次寫的是時候是最外層是i,然後是i 2行,最內層是i 1行。其實由於第i行的狀態是由前兩行得到,而i 1行是由i 2...