思路:其实这题不难,关键是状态的储存。我设置了map1和map2用于储存当前状态和下一状态,在函数check(见以下代码)中,当map1储存当前状态时,map2就是下一状态,反之亦然。另外一个关键点是怎么判断3×3区域内黑多还是白多,我设置了一个值BLACK = 5*'b'+4*'w',这是黑多于白的临界情况,由于' b ' < ' w ',所以当3×3区域内所有字符的ASC2码相加的结果大于BLACK时,就是白多,反之黑多。
AC Code:
#include <stdio.h>
#include <string.h>
#define BLACK 5*'b'+4*'w'
char map1[513][513], map2[513][513];
int flag, b;
int m, t;
void check(int i, int j)
{
if(flag > 0)
{
if(map1[i-1][j-1] + map1[i][j-1] + map1[i+1][j-1] + map1[i-1][j] + map1[i+1][j] + map1[i-1][j+1] + map1[i][j+1] + map1[i+1][j+1] + map1[i][j] > BLACK)
{
/*1.当且仅当当前状态为b时才执行b--。2.注意map2[i][j] = 'w'不能放在if中
因为无论if中的条件是否为真,此指令都需要执行,因为map1[i][j] == 'w'(if
判断条件为假)时不意味着map2[i][j] == 'w'。如果不理解可以把程序后附上的
例子执行一次*/
if(map1[i][j] == 'b')
b--;
map2[i][j] = 'w';
}
else
{
if(map1[i][j] == 'w')
b++;
map2[i][j] = 'b';
}
}
else
{
if(map2[i-1][j-1] + map2[i][j-1] + map2[i+1][j-1] + map2[i-1][j] + map2[i+1][j] + map2[i-1][j+1] + map2[i][j+1] + map2[i+1][j+1] + map2[i][j] > BLACK)
{
if(map2[i][j] == 'b')
b--;
map1[i][j] = 'w';
}
else
{
if(map2[i][j] == 'w')
b++;
map1[i][j] = 'b';
}
}
}
int main()
{
int n;
scanf("%d", &n);
while(n--)
{
scanf("%d%d", &m, &t);
for(int i = 0; i < m; i++)
{
scanf("%s", map1[i]);
strcpy(map2[i], map1[i]);
}
//for(int i=0; i<m; i++) puts(map2[i]);
flag = 1; b = 0;
for(int i = 0; i < m; i++)
{
for(int j = 0; j < m; j++)
if(map1[i][j] == 'b')
b++;
}
//printf("%d %d", b, w);
while(t--)
{
for(int i = 1; i < m-1; i++)
{
for(int j = 1; j< m-1; j++)
check(i, j);
}
flag = -flag;
}
//for(int i = 0; i < m; i++) puts(map2[i]);
printf("%d %d\n", b, m * m - b);
}
return 0;
}
3 3
www
wdw
www