传送门
显然当没有'?' 时,模拟一遍即可
当位置i 是'?' 时,如果后续的关卡中,位置i 需要关灯,且当前关卡必须关掉一些灯,则顺手关掉
开灯也同理
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std ;
const int inf=1e9 +7 ;
const int N = 50 +5 ;
char str[N][N];
int to[N][N];
int now[N];
void initTo(int n,int m){
for (int i=0 ;i<n;++i){
for (int j=0 ;j<m;++j){
switch (str[i][j]){
case '-' :
to[i][j]=0 ;
break ;
case '+' :
to[i][j]=1 ;
break ;
case '?' :
to[i][j]=2 ;
for (int k=i+1 ;k<n;++k){
if (str[k][j]!='?' ){
to[i][j]=2 +(str[k][j]=='+' );
break ;
}
}
break ;
}
}
}
}
int slove(int n,int m){
initTo(n,m);
int ans=n;
MEM(now,0 );
for (int i=0 ;i<n;++i){
bool mustOpen=0 ;
bool mustClose=0 ;
for (int j=0 ;j<m;++j){
if (to[i][j]==0 &&now[j]==1 ){
mustClose=1 ;
}
if (to[i][j]==1 &&now[j]==0 ){
mustOpen=1 ;
}
}
ans+=mustOpen+mustClose;
for (int j=0 ;j<m;++j){
if (to[i][j]<2 ){
now[j]=to[i][j];
}
if (mustClose&&to[i][j]==2 ){
now[j]=0 ;
}
if (mustOpen&&to[i][j]==3 ){
now[j]=1 ;
}
}
}
return ans;
}
int main(){
int T;
scanf ("%d" ,&T);
while (T--){
int n,m;
scanf ("%d%d" ,&n,&m);
for (int i=0 ;i<n;++i){
scanf ("%s" ,str[i]);
}
printf ("%d\n" ,slove(n,m));
}
return 0 ;
}