简单的状压dp
因为炮兵的攻击范围是两格,所以状态要多开一维
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200;
const int log = 11;
int dp[maxn][maxn][maxn];
char Map[maxn][log];
int bmap[maxn];
void cTb(int n,int m){
for(int i=0;i<n;i++){
int t = 0;
for(int j=0;j<m;j++){
t = t * 2 + (Map[i][j] == 'H'?1:0);
}
bmap[i] = t;
}
}
bool juder(int a,int b,int c){
return (a&b)==0 && (b&c)==0 && (c&a)==0;
}
bool able(int x){
return juder(x,x<<1,x<<2);
}
int calp(int x){
int ret = 0;
while(x){
ret += x%2;
x/=2;
}
return ret;
}
int state[maxn];
int main(){
int n,m;
int lener = 0;
for(int i=0;i<(1<<log);i++){
if(able(i))
state[lener++] = i;
}
while(~scanf("%d %d",&n,&m)){
for(int i=0;i<n;i++){
scanf("%s",Map[i]);
}
memset(dp,0,sizeof(dp));
cTb(n,m);
int len = 1<<m;
for(int i=0;state[i]<len;i++){
if((state[i]&bmap[0])==0){
dp[0][i][0] = max(dp[0][i][0],calp(state[i]));
}
}
if(n>1){
for(int i=0;state[i]<len;i++){
for(int j=0;state[j]<len;j++){
if((state[i]&state[j])!=0 || (state[j]&bmap[1])!=0) continue;
dp[1][j][i] = max(dp[1][j][i],calp(state[j])+dp[0][i][0]);
}
}
}
if(n>2){
for(int i=2;i<n;i++){
for(int j=0;state[j]<len;j++){
for(int k=0;state[k]<len;k++){
for(int l=0;state[l]<len;l++){
if((state[l]&bmap[i])==0 && juder(state[j],state[k],state[l]))
dp[i][l][k] = max(dp[i][l][k],calp(state[l])+dp[i-1][k][j]);
}
}
}
}
}
int ans = 0;
for(int i=0;state[i]<len;i++){
for(int j=0;state[j]<len;j++){
ans = max(ans,dp[n-1][i][j]);
}
}
printf("%d\n",ans);
}
return 0;
}