北方有小仙儿 @ 2018-09-03 11:26:04
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
int n,m;
long long ans;
long long f[1500][1500][4],sum[1500];
//滚动数组防爆空间 f[k][j][i] 表示当前行状态为j,前一行状态为k,已经处理到i行
struct edge{
int s[1500];
int num;
}a[105];
void prepare(int x,long long t)
{
for(int i=0;i<(1<<m);i++)
{
if((i&t)||(i&(i<<1))||(i&(i<<2)))continue;
a[x].num++;
a[x].s[a[x].num]=i;
int k=0;
if(sum[i]==0)//sum统计有几个炮兵
{
for(int j=1;j<=m;j++)
if(i&(1<<j))k++;
sum[i]=k;
}
}
}
void dp()
{
for(int i=1;i<=a[1].num;i++)f[0][i][1]=sum[i];//第一行初始
for(int i=1;i<=a[1].num;i++)
for(int j=1;j<=a[2].num;j++)
if(a[1].s[i]&a[2].s[j])continue;
else f[i][j][2]=sum[i]+sum[j];//第二行初始
for(int i=3;i<=n;i++)//当前行数
for(int k=1;k<=a[i-1].num;k++)// 前一行状态
for(int j=1;j<=a[i].num;j++)//当前行状态
for(int z=1;z<=a[i-2].num;z++)//上上行状态
if((a[i].s[j]&a[i-1].s[k])||(a[i].s[j]&a[i-2].s[z])||(a[i-1].s[k]&a[i-2].s[z]))continue;
else {
f[k][j][i%3]=max(f[k][j][i%3],f[z][k][(i-1)%3]+sum[j]);
ans=max(f[k][j][i%3],ans);
}
cout<<ans;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
long long t=0;
char x[15];
cin>>x;
for(int j=0;j<m;j++)
{
if(x[j]=='H')t=(t<<1)+1;
if(x[j]=='P')t=(t<<1)+0;
}
prepare(i,t);
}
dp();
return 0;
}