/*
dp[i][j][k]为第i行的数在第i-1的状态为j第i行的状态为k的最大值
状态转移方程 dp[i][j][k]=max(dp[i][j][k],dp[i-1][s][j]+count(k))
count(k)为状态是k的时候能排的士兵
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 110
#define maxs 61
char str[maxn][maxn];
int dp[maxn][maxs][maxs];
int useful[maxs];//记下有用的状态
int landstatus[maxn];//记录这个图用二进制表示每一行的状态
int n;int m; //'H'时为1'P'时为0 每一行都有一个状态
//那么判断所选状态能否在该行可行的条件就是‘&’是否为0
int count(int x) //计算状态x所排的士兵
{
int ans=0;
int t=x;
while(t)
{
if(t%2)
ans++;
t/=2;
}
return ans;
}
int init() //找出所有可行的行状态
{
int upper=1<<m;
int k=0;int i;
for(i=0;i<upper;i++)
{
if((i&(i<<1))||(i&(i<<2)))
continue;
useful[k++]=i;
}
return k;
}
int main()
{
int i,j,k,s;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(landstatus,0,sizeof(landstatus));
memset(dp,-1,sizeof(dp));
for(i=0;i<n;i++)
{
scanf("%s",str[i]);
for(j=0;j<m;j++)
if(str[i][j]=='H')
landstatus[i]+=(1<<j);
}
int topper=init();
for(j=0;j<topper;j++)
{
if(useful[j]&landstatus[0])
continue;
dp[0][0][j]=count(useful[j]);
}
for(i=1;i<n;i++)
for(k=0;k<topper;k++)//枚举第i行的情况
{
if(useful[k]&landstatus[i])//判断是否该状态是否在这一行可行
continue;
for(j=0;j<topper;j++)//枚举第i-1的情况
{
if(useful[j]&useful[k])//判断该列是否与前一列冲突
continue;
for(s=0;s<topper;s++)//枚举第i-2的情况
{
if(useful[k]&useful[s])//判断该列是否与前两列冲突
continue;
if(dp[i-1][s][j]==-1)//判断dp[i-1][s][j]是否有可能到达
continue;
dp[i][j][k]=max(dp[i][j][k],dp[i-1][s][j]+count(useful[k]));
}
}
}
int ans=0;
for(j=0;j<topper;j++)
for(k=0;k<topper;k++)
ans=max(ans,dp[n-1][j][k]);
printf("%d\n",ans);
}
}
dp[i][j][k]为第i行的数在第i-1的状态为j第i行的状态为k的最大值
状态转移方程 dp[i][j][k]=max(dp[i][j][k],dp[i-1][s][j]+count(k))
count(k)为状态是k的时候能排的士兵
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 110
#define maxs 61
char str[maxn][maxn];
int dp[maxn][maxs][maxs];
int useful[maxs];//记下有用的状态
int landstatus[maxn];//记录这个图用二进制表示每一行的状态
int n;int m; //'H'时为1'P'时为0 每一行都有一个状态
//那么判断所选状态能否在该行可行的条件就是‘&’是否为0
int count(int x) //计算状态x所排的士兵
{
int ans=0;
int t=x;
while(t)
{
if(t%2)
ans++;
t/=2;
}
return ans;
}
int init() //找出所有可行的行状态
{
int upper=1<<m;
int k=0;int i;
for(i=0;i<upper;i++)
{
if((i&(i<<1))||(i&(i<<2)))
continue;
useful[k++]=i;
}
return k;
}
int main()
{
int i,j,k,s;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(landstatus,0,sizeof(landstatus));
memset(dp,-1,sizeof(dp));
for(i=0;i<n;i++)
{
scanf("%s",str[i]);
for(j=0;j<m;j++)
if(str[i][j]=='H')
landstatus[i]+=(1<<j);
}
int topper=init();
for(j=0;j<topper;j++)
{
if(useful[j]&landstatus[0])
continue;
dp[0][0][j]=count(useful[j]);
}
for(i=1;i<n;i++)
for(k=0;k<topper;k++)//枚举第i行的情况
{
if(useful[k]&landstatus[i])//判断是否该状态是否在这一行可行
continue;
for(j=0;j<topper;j++)//枚举第i-1的情况
{
if(useful[j]&useful[k])//判断该列是否与前一列冲突
continue;
for(s=0;s<topper;s++)//枚举第i-2的情况
{
if(useful[k]&useful[s])//判断该列是否与前两列冲突
continue;
if(dp[i-1][s][j]==-1)//判断dp[i-1][s][j]是否有可能到达
continue;
dp[i][j][k]=max(dp[i][j][k],dp[i-1][s][j]+count(useful[k]));
}
}
}
int ans=0;
for(j=0;j<topper;j++)
for(k=0;k<topper;k++)
ans=max(ans,dp[n-1][j][k]);
printf("%d\n",ans);
}
}