题目描述
司令部的将军们打算在 N×M�×� 的网格地图上部署他们的炮兵部队。
一个 N×M�×� 的地图由 N� 行 M� 列组成,地图的每一格可能是山地(用 HH 表示),也可能是平原(用 PP 表示),如下图。
在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。
图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
输入
第一行包含两个由空格分割开的正整数,分别表示 N� 和 M�。
接下来的 N� 行,每一行含有连续的 M� 个字符,按顺序表示地图中每一行的数据。
N≤100�≤100,M≤10�≤10,保证字符仅包含 `P` 与 `H`。
输出
一行一个整数,表示最多能摆放的炮兵部队的数量。
样例输入
5 4
PHPP
PPHH
PPPP
PHPP
PHHP
样例输出
6
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN=210;
bool isAttackAlly(int x){
if((x&(x<<1))||(x&(x<<2)))return 1;
return 0;
}
int countSoldier(int x){
int cnt=0;
while(x){
cnt++;
x=x&(x-1);
}
return cnt;
}
int m;
int cur[MAXN],soldierCnt[MAXN],top;
void init(){
for(int i=0;i<(1<<m);i++){
if(!isAttackAlly(i)){
cur[++top]=i;
soldierCnt[top]=countSoldier(i);
}
}
}
int hills[MAXN];
bool isInHill(int x,int status){
return status&hills[x];
}
bool isCompatible(int a,int b,int c){
if((a&b)||(a&c)||(b&c))return 0;
return 1;
}
int f[MAXN][80][80];
char a[110][11];
int main(){
int n;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
char tmp;
for(int j=1;j<=m;j++){
cin>>tmp;
if(tmp=='H'){
hills[i]|=(1<<(m-j));
}
}
}
init();
for(int i=1;i<=top;i++){
int nowValue=cur[i];
if(!isInHill(1,nowValue)){
f[1][1][i]=soldierCnt[i];
}
}
for(int x=2;x<=n;x++){
for(int i=1;i<=top;i++){//first row
int nowValue1=cur[i];
if(isInHill(x-2,nowValue1))continue;
for(int j=1;j<=top;j++){//second row
int nowValue2=cur[j];
if(isInHill(x-1,nowValue2))continue;
for(int k=1;k<=top;k++){//third row
int nowValue3=cur[k];
if(isInHill(x,nowValue3))continue;
if(isCompatible(nowValue1,nowValue2,nowValue3)){
f[x][j][k]=max(f[x][j][k],f[x-1][i][j]+soldierCnt[k]);
}
}
}
}
}
int ans=-1;
for(int i=1;i<=top;i++){
for(int j=1;j<=top;j++){
ans=max(ans,f[n][i][j]);
}
}
printf("%d\n",ans);
return 0;
}