/**
结题思路:用dp[r][i][j]表示第r行r行状态为i,r-1行状态为j时的最大可部署炮兵的个数。通过求解合法状态,缩小需要遍历的状态范围。同时求出各个合法状态的二进制中1的个数,然后特殊处理首行,然后dp求解每行每种可行状态对应的可部兵的最大个数。状态转移方程dp[r][i][j]=max(dp[r][i][j],dp[r-1][j][k]+num_1[i])。
*/
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
int n,m,top,num_legal;
char Map[110][15];
int dp[105][1<<6][1<<6];
//dp[r][i][j]表示第r行的状态为i,第r-1行的状态为j时的最多放的炮兵数
//可以发现虽然m值最大是10,但是合法的状态值最多60个
int an_Map[110];//将每行的图用状态值表示0代表原图为P,1代表H
int legal[1<<6];//将合法的状态放入数组,即不会互相攻击的状态
int num_1[1<<6];//记录每个合法状态值得二进制中1的个数
int max(int x,int y){
return x>y?x:y;
}
bool jud_legal(int x){
//相邻或只隔了一个位置为非法,相隔两个位置为合法
if(x&(x<<1))return false;
if(x&(x<<2))return false;
return true;
}
int get_num(int x){
//得到x的二进制中1的个数
int tmp_num=0;
while(x){
if(1&x)
tmp_num++;
x>>=1;
}
return tmp_num;
}
void solve_legal(){
top=1<<m; //合法状态的最大值
num_legal=0; //合法状态的个数
for(int i=0;i<top;i++){
if(jud_legal(i)){ //判断该状态是否合法
legal[num_legal]=i;
num_1[num_legal++]=get_num(i);
}
}
}
void init(){
memset(dp,-1,sizeof(dp)); //初始化为-1表示不可部兵
memset(an_Map,0,sizeof(an_Map));
memset(legal,0,sizeof(legal));
memset(num_1,0,sizeof(num_1));
}
void solve_Map(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(Map[i][j]=='H'){
an_Map[i]+=(1<<(m-j)); //将原图的每行都用一个数值表示图状态
}
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
if(n==0||m==0){
printf("%d\n",0);
continue;
}
init();
getchar();
for(int i=1;i<=n;i++){
gets(Map[i]+1);
}
solve_legal(); //处理出合法状态的数组
solve_Map(); //处理出图的数字化表示数组
for(int j=0;j<num_legal;j++){ //将第一行做特殊处理
if((an_Map[1]&legal[j])==0){//如首行图不与该合法状态冲突
//将该合法状态可部兵数赋给首行对应状态的dp数组
//0行状态为0不会对下面的情况产生影响
dp[1][j][0]=num_1[j];
}
}
for(int r=2;r<=n;r++){
for(int i=0;i<num_legal;i++){
if(legal[i]&an_Map[r]) //r行合法状态与r行图冲突
continue;
for( int j=0;j<num_legal;j++){
if(legal[i]&legal[j])continue;//r行合法状态与r-1行合法状态冲突
for(int k=0;k<num_legal;k++){
if(legal[k]&legal[i])continue;//r-2行合法状态和r行合法状态冲突
if(legal[k]&legal[j])continue;//r-2行合法状态和r-1行合法状态冲突
if(dp[r-1][j][k]==-1)continue;
//可以不加本语句。没更新过,不会对该dp值的最大值产生影响
dp[r][i][j]=max(dp[r][i][j],dp[r-1][j][k]+num_1[i]);
}
}
}
}
int ans=-1;
for(int j=0;j<num_legal;j++){
for(int k=0;k<num_legal;k++){
//遍历所有状态求出最值
ans=max(ans,dp[n][j][k]);
}
}
printf("%d\n",ans);
}
return 0;
}