POJ 1185 炮兵陣地 狀態壓縮DP

2021-08-11 18:03:39 字數 3133 閱讀 4440

time limit: 2000ms memory limit: 65536k

total submissions: 14881 accepted: 5580

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

對於第k行哪些點放炮兵使得1~k行炮兵數最多與第k-1,k-2行哪些點放炮兵有關,所以對於第k行需要前面兩行的(k-1,k-2)的狀態才能確定。

所以對於第k行需要前面兩行的(k-1,k-2)的狀態才能確定,最暴力的方法莫過於dp[k-1]…[k-2],表示第k-1行第1,2,3..個位置放與不放炮兵並且第k-2個位置放與不放炮兵時來確定第k行的dp..

但顯然這樣開是不現實的 , 所以 我們可以用dp思路來解決這道題,炮兵的位置可以用狀態壓縮來處理。

/*

p|(1

#include

#include

#include

#define inf 99999999

typedef

long

long ll;

using

namespace

std;

const

int max=100+10;

int n,m,lastsize,lastlastsize,nowsize; //nowsize當前行的方案數,lastsize上一行的方案數, lastlastsize的方案數

int last[max],lastlast[max],now[max]; // now[i]第i行的方案......

int num[max],dp[max][max],temp[max][max]; //dp[i][j] i代表當前行 j代表上一行

//temp[j][t] j上一行 t上上行

char map[max][max];

void dfs(int id,int k,int p,int sum)

if(map[id][k] == 'p') //找到可安放炮兵的位置

dfs(id,k+3,p|(1

<1);

dfs(id,k+1,p,sum);

} void dp()

} int main()

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

} return

0;

}

分析:狀態壓縮dp,這種題一般狀態不多,這道題最多有10列,原本每行最多有2^10種狀態,但題目有限制(同行同列的兩個炮塔間距離至少為2),狀態就最多只有60種

dp[i][r1][j]:遍歷到第i行,前一行狀態為r1,當前狀態為j的最大結果

轉移方程:dp[i][r1][j]=max;

#include

int max(int a,int b)

int dp[100][60][60];

int st[60];//每種狀態的二進位制數

int sum[60];//每種狀態的炮塔數

int col[100];//按列存放每一行1(指高地)的分布

int cnt;//合法狀態總數

char s[10];

bool j(int x)

int getsum(int x)

return res;

}void pre(int m)

}void clear(int x)

int main()}}

}int ans=0;

for(i=0;ifor(j=0;j1][i][j]);

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

}return

0;}

由於狀態轉移時dp[i]只和dp[i-1]有關,故可以利用滾動陣列優化空間

#include

int max(int a,int b)

int dp[2][60][60],st[60],sum[60],col[100],cnt;

char s[10];

bool j(int x)

int getsum(int x)

return res;

}void pre(int m)

}void clear(int x)

int main()}}

}int ans=0;

for(i=0;ifor(j=0;jprintf("%d\n",ans);

}return

0;}

poj1185 炮兵陣地(狀態壓縮)

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

poj 1185炮兵陣地(狀態壓縮)

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

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...