写模拟类型的题是细致活……
#include "stdio.h"
#include "string.h"
int m[301][301];
int r, c;
int row[301][301], col[301][301];
int main(){
int z, i, j, k, c1, c0, t, sum;
freopen("in.txt", "r", stdin);
scanf("%d", &z);
while(z--){
scanf("%d %d", &r, &c);
for(i=1; i<=r; i++){
for(j=1; j<=c; j++)
scanf("%d", &m[i][j]);
}
memset(row, 0, sizeof(row));
memset(col, 0, sizeof(col));
for(i=1; i<=r; i++){ //做个预处理,统计每一行,每一列 1 的个数
for(j=1; j<=c; j++){
if(m[i][j]){
row[i][j] = row[i][j-1]+1;
col[i][j] = col[i-1][j]+1;
}
else{
row[i][j] = row[i][j-1];
col[i][j] = col[i-1][j];
}
}
}
sum = 0;
for(i=1; i<=r-1; i++){
for(j=1; j<=c-1; j++){
if(!m[i][j] || !m[i+1][j] || !m[i][j+1])
continue;
if(m[i+1][j+1])
sum++;
c1 = c0 = 0;
for(k=2; i+k<=r && j+k<=c; k++){
if(!m[i+k][j] || !m[i][j+k]) break;
t = row[i+k-1][j+k-1]-row[i+k-1][j] + col[i+k-1][j+k-1]-col[i][j+k-1] -m[i+k-1][j+k-1]; //注意减去对角上的1
c0 += (k-1)*2-1 - t;
c1 += t;
t = row[i+k][j+k]-row[i+k][j-1] + col[i+k][j+k]-col[i-1][j+k] -m[i+k][j+k];
if(t != (k+1)*2-1) continue;
if((c0>c1?(c0-c1):(c1-c0))<=1)
sum++;
}
}
}
printf("%d\n", sum);
}
return 0;
}