题目描述
一个n×n格棋盘,某些格子里放了黑棋或者白棋,按行,列,对角方向,数棋子。如果同颜色同方向的连续的棋子达到3个或者以上,我们称之为“杠”。 注意如果有3个以上的同色连续棋子,并不会算成多条“杠”,只会算为一条。比如有4个黑棋连成一行,这时这4颗黑棋只算一条杠。请计算一下棋盘上黑棋和白棋都有多少条“杠”?
输入格式
第一行是一个整数T (1≤T≤100),表示样例的个数。
以后每个样例的第一行是一个整数n (3≤n≤15),表示棋盘的大小。
以后的n行,每行n个字母,表示棋盘的格子的情况。字母只含B
,W
,.
,分别表示黑棋,白棋,空格。
输出格式
依次输出每个样例的结果,每个样例输出一行,为两个整数,表示棋局中黑棋和白棋的杠的数量,两者用一个空格隔开。
样例输入
2 4 BBBB W... WW.. W.W. 3 WWW WWW WWW
样例输出
1 2 0 8
样例解释
黑棋只有第一行的4颗组成一条杠; 白棋从(2,1)出发,往下,和往右下的组成2条杠。
第二个样例白棋三横三竖两个对角,一共8个。
思路:
从一个坐标开始遍历该坐标为起点的一行,一列和两对角线,为了简化遍历条件判断,将二维数组开到20,防止遍历时越界,只需要比较与当前坐标为起点相邻的2个值,为了避免3个以上连续字母重复计数,如果该坐标在该方向前值相同,将数目cnt置为0;
每次需要将数组重新置0;
代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int t;
scanf("%d",&t);
char s[20][20];
char c[2] = {'B','W'};
int cout[2] ={0,0};//记录black和white的个数
while(t--){
memset(s,0,sizeof(s));//多案例必须每次置零防止上一次遗留
memset(cout,0,sizeof(cout));
int n;
scanf("%d",&n);
// for(int i=1;i<=n;i++){
// for(int j = 1;j<=n;j++){
// scanf(" %c",&s[i][j]);//前加上空格表示跳过换行
// }
// }
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
for(int i=1;i<=n;i++){//统计每一行
for(int j = 1;j<=n;j++){
for(int k=0;k<2;k++){
int cnt = 0;
if(s[i][j]==c[k])//起点
{
if(s[i][j+1] == c[k])//计算每行
cnt++;
if(s[i][j+2] == c[k])
cnt++;
if(s[i][j-1] == c[k])
cnt = 0;//已经存在3个,已经计数
if(cnt==2)
cout[k]++;
cnt = 0;
if(s[i+1][j] == c[k])//计算每列
cnt++;
if(s[i+2][j] == c[k])
cnt++;
if(s[i-1][j] == c[k])
cnt = 0;//已经存在3个,已经计数
if(cnt==2)
cout[k]++;
cnt = 0;
if(s[i+1][j+1] == c[k])//主对角线
cnt++;
if(s[i+2][j+2] == c[k])
cnt++;
if(s[i-1][j-1] == c[k])
cnt = 0;//已经存在3个,已经计数
if(cnt==2)
cout[k]++;
cnt = 0;
if(s[i+1][j-1] == c[k])//次对角线
cnt++;
if(s[i+2][j-2] == c[k])
cnt++;
if(s[i-1][j+1] == c[k])
cnt = 0;//已经存在3个,已经计数
if(cnt==2)
cout[k]++;
cnt = 0;
}
}
}
}
printf("%d %d\n",cout[0],cout[1]);
}
return 0;
}