基礎的狀態壓縮DP,考慮到第i行和第i-1、第i-2行有直接的關係,於是不難得出:dp[i][j][k] 代表第i行記錄了第i行的狀態"j"和第i-1行的狀態"k",這裏的狀態就是二進制的狀態,然後加上一個judge判斷就行。
附代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn =70;
char Map[111][12];
int n,m,num;
int hash[maxn];
int dp[111][maxn][maxn];
bool judge(int now,int tot){
int kk=m-1;
while(tot){
if(tot%2){
if(Map[now][kk]=='H'){
return false;
}
}
tot>>=1;
kk--;
}
return true;
}
int getval(int tot){
int sum=0;
while(tot){
if(tot%2) sum++;
tot>>=1;
}
return sum;
}
void init(){
int Max=(1<<m)-1;
for(int i=0;i<=Max;i++){
if((!(i&(i<<2))) && (!(i&(i<<1)))){
hash[num++]=i;
}
}
}
int main(){
while(~scanf("%d %d",&n,&m)){
for(int i=0;i<n;i++){
scanf("%s",Map[i]);
}
num=0;
if(n==0 || m==0){
printf("0\n");
continue;
}
memset(dp,0,sizeof(dp));
init();
for(int i=0;i<n;i++){
for(int j=0;j<num;j++){
int tmp_1=hash[j];
if(!judge(i,tmp_1)){
continue;
}
int tmp_j=getval(tmp_1);
if(!i) dp[i][j][0]=tmp_j;
else{
for(int k=0;k<num;k++){
int tmp_2=hash[k];
if(!judge(i-1,tmp_2)) continue;
if(!(tmp_1 & tmp_2)){
if(i<2) dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][0]+tmp_j);
else{
for(int p=0;p<num;p++){
int tmp_3=hash[p];
if(!judge(i-2,tmp_3)) continue;
if((!(tmp_1 & tmp_3)) && (!(tmp_2 & tmp_3)) )
dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+tmp_j);
}
}
}
}
}
}
}
int ans=-1;
for(int i=0;i<num;i++){
for(int j=0;j<num;j++)
ans=max(ans,dp[n-1][i][j]);
}
printf("%d\n",ans);
}
}