注意输入方式,和多操作的处理(利用规律简化操作次数)以防TLE
//超时版本(虽然结果正确)
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
char str[1001][1001];
//把棋盘str中的每个棋子的黑白状态相应地表示在整型数组flag中
int flag[1001][1001];
int main(void)
{
int T, N, Q, x, y, count;
cin >> T;
for (int i = 1; i <= T; ++i)
{
cin >> N;
count = 0;
for (int j = 0; j < N; ++j) cin >> str[j];
for (int j = 0; j < N; j++)
{
for (int k = 0; k < N; k++)
{
if (str[j][k] == 'w') flag[j][k] = 1; //1 表示 白
else flag[j][k] = 0; //0 表示 黑
}
}
cin >> Q;
//下面对于每个命令,都对行和列的全部元素翻动一次,导致超时
while (Q--)
{
cin >> x >> y;
for (int i = 0; i < N; i++)
{
flag[x - 1][i] ^= 1;
flag[i][y - 1] ^= 1;
}
}
for (int j = 0; j < N; ++j)
{
for (int k = 0; k < N; ++k)
{
if (flag[j][k] == 1) count++;
}
}
cout << "Case #" << i << ": " << count << endl;
}
return 0;
}
//改进版本
#include<iostream>
#include<string.h>
using namespace std;
char str[1001][1001];
//用a,b两个数组来分别表示对str矩阵的行列的操作,其中值为0表示原封不动,1表示翻动一次
//tips:当一行(一列)被翻动偶数次,则相当于原封不动;若被翻动奇数次,则相当于被翻动一次
//注意要翻动的行列的交叉点也就相当于没有翻动
int a[1001], b[1001];
int main(void)
{
int T, N, Q, x, y, count;
cin >> T;
for (int i = 1; i <= T; ++i)
{
cin >> N;
count = 0;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
//若使用两个for循环嵌套逐个输入字符str[j][k],则会超时,故采用字符串输入
for (int j = 0; j < N; ++j) cin >> str[j];
cin >> Q;
while (Q--)
{
cin >> x >> y;
a[x - 1] = 1 - a[x - 1]; //或者a[x - 1] ^= 1;
b[y - 1] ^= 1; //或者b[y - 1] = 1 - b[y - 1];
}
for (int j = 0; j < N; ++j)
{
for (int k = 0; k < N; ++k)
{
if (a[j] + b[k] == 1) //该点总共被翻动奇数次
{
if (str[j][k] == 'b') count++;
}
else 该点总共被翻动偶数次
{
if (str[j][k] == 'w') count++;
}
}
}
cout << "Case #" << i << ": " << count << endl;
}
return 0;
}