思路:
经典的状态压缩题,我是来存代码的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long int64;
const int INF = 0x3f3f3f3f;
const int MAX_STATE = (1<<10)+10;
const int MAXN = 110;
int n, m;
int mat[MAXN], maxState;
int f[2][65][65], idx, sta[65], num[65];
inline int check(int sta){
int cnt = 0;
for(int i=0; i<m; ++i){
if( (sta>>i)&1 ){
++cnt;
for(int j=1; j<=2; ++j){
if(i-j>=0 && (sta>>(i-j))&1) return 0;
if(i+j<m && (sta>>(i+j))&1) return 0;
}
}
}
return cnt;
}
inline void init(){
maxState = (1<<m)-1;
idx = 1;
for(int i=1; i<=maxState; ++i){
int ret = check(i);
if(ret){
num[idx] = ret;
sta[idx++] = i;
}
}
}
int dp(){
memset(f, 0, sizeof(f));
int pt = 0;
int ans = 0;
for(int i=0; i<n; ++i){
pt = !pt;
for(int j=0; j<idx; ++j){
if( (mat[i]&sta[j]) != sta[j] ) continue;
if(i==0){
f[pt][j][0] = num[j];
ans = max(ans, num[j]);
}else if(i==1){
for(int k=0; k<idx; ++k){
if( (mat[i-1]&sta[k]) != sta[k]
|| (sta[j]&sta[k]) ) continue;
f[pt][j][k] = f[!pt][k][0] + num[j];
ans = max(ans, f[pt][j][k]);
}
}else {
for(int k=0; k<idx; ++k){
if( (mat[i-1]&sta[k])!=sta[k]
|| (sta[j]&sta[k]) ) continue;
int maxx = 0;
for(int l=0; l<idx; ++l) {
if( (mat[i-2]&sta[l])!=sta[l]
|| (sta[l]&sta[j])
|| (sta[l]&sta[k])) continue;
maxx = max(maxx, f[!pt][k][l]);
}
f[pt][j][k] = maxx + num[j];
ans = max(ans, f[pt][j][k]);
}
}
}
}
return ans;
}
int main(){
while(~scanf("%d%d%*c", &n, &m)){
// input
memset(mat, 0, sizeof(mat));
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
if(getchar()=='P'){
mat[i] |= (1<<j);
}
}
getchar();
}
init();
printf("%d\n", dp());
}
return 0;
}