炮兵陣地
| Time Limit: 2000MS |
|
Memory Limit: 65536K |
| Total Submissions: 15275 |
|
Accepted: 5749 |
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 4PHPPPPHHPPPPPHPPPHHP Sample Output 6 Source Noi 01 |
思路:
狀態要設定三個因為和上面兩個狀態因為炮兵的攻擊範圍是影響下三行有關,dp[i][j][k] 表示第i行狀態為k,第i-1狀態為j時的最大炮兵個數。 狀態轉移方程:
dp[i][j][k] =max(dp[i][j][k],dp[i-1][l][j]+sum[k]); sum[k]為k狀態中1的個數 ;
#include <iostream>#include<stdio.h>#include<string.h>#define MAX(a,b) ((a)>(b)?(a):(b))using namespace std;int dp[101][65][65];//dp[i][j][k]表示上上行狀態為i上行狀態為j本行狀態為k的最多炮兵數int state[105];//記錄一行時可以放的狀態int sum[105];//記錄每一種狀態對應放得炮兵數int maze[105];//讀每行地圖int n,m,cnt;int isok(int x)//判斷每行內是否衝突{ if(x&(x>>1))//判斷相鄰位是否有炮兵 return 0; if(x&(x>>2))//判斷隔一位是否有炮兵 return 0; return 1;}int getone(int x)//計算每種狀態一的個數.即炮兵數{ int one=0; while(x>0) { if(x&1) one++; x>>=1; } return one;}int main(){ int i,j,now,pre,ppre,ans; char c; while(~scanf("%d%d",&n,&m)) { getchar(); cnt=0; for(i=0; i<(1<<m); i++) if(isok(i))//預先處理.先得到一行可行狀態 { state[cnt]=i; sum[cnt++]=getone(i); } ans=0; memset(maze,0,sizeof maze); memset(dp,0,sizeof dp); for(i=1; i<=n; i++) { for(j=0; j<m; j++)//處理地圖.把地圖變成01序列 { scanf("%c",&c); if(c=='H')//是h就記為1.方便後面判斷是否與地圖衝突 maze[i]=maze[i]|(1<<j); } getchar(); } for(i=0;i<cnt;i++) if(!(state[i]&maze[1]))//初始化第一行 dp[1][0][i]=sum[i]; for(i=2;i<=n;i++) { for(now=0;now<cnt;now++)//枚舉本行狀態 { if(state[now]&maze[i])//判斷本行狀態與地圖是否衝突 continue; for(pre=0;pre<cnt;pre++)//枚舉前一行 { if(state[pre]&maze[i-1]) continue; if(state[now]&state[pre])//本行與前一行是否衝突 continue; for(ppre=0;ppre<cnt;ppre++)//枚舉上上行 { if(state[ppre]&state[now]) continue; if(state[ppre]&state[pre]) continue; if(state[ppre]&maze[i-2]) continue; dp[i][pre][now]=MAX(dp[i][pre][now],dp[i-1][ppre][pre]+sum[now]); } } } } for(i=0;i<cnt;i++) for(j=0;j<cnt;j++) if(dp[n][i][j]>ans) ans=dp[n][i][j]; printf("%d\n",ans); } return 0;}