Flip Game
Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Problem Description
Flip game is played on a square N*N field with two-sided pieces placed on each of its N^2 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. The rows are numbered with integers from 1 to N upside down; the columns are numbered with integers from 1 to N from the left to the right. Sequences of commands (x
i, y
i) are given from input, which means that both pieces in row x
i and pieces in column y
i will be flipped (Note that piece (x
i, y
i) will be flipped twice here). Can you tell me how many white pieces after sequences of commands?
Consider the following 4*4 field as an example:
bwww
wbww
wwbw
wwwb
Here "b" denotes pieces lying their black side up and "w" denotes pieces lying their white side up.
Two commands are given in order: (1, 1), (4, 4). Then we can get the final 4*4 field as follows:
bbbw
bbwb
bwbb
wbbb
So the answer is 4 as there are 4 white pieces in the final field.
Input
The first line contains a positive integer T, indicating the number of test cases (1 <= T <= 20).
For each case, the first line contains a positive integer N, indicating the size of field; The following N lines contain N characters each which represent the initial field. The following line contain an integer Q, indicating the number of commands; each of the following Q lines contains two integer (x
i, y
i), represent a command (1 <= N <= 1000, 0 <= Q <= 100000, 1 <= x
i, y
i <= N).
Output
For each case, please print the case number (beginning with 1) and the number of white pieces after sequences of commands.
Sample Input
2
4
bwww
wbww
wwbw
wwwb
2
1 1
4 4
4
wwww
wwww
wwww
wwww
1
1 1
Sample Output
思路:
第一步,判断field中有哪些行和列需要进行反转,将这些行和列保存到数组中。(使用了异或操作),对一行(列)改变偶数次等于没改变;改变奇数次,相当于改变了一次(反转)。
第二步,通过对行列的改变次数,确定field中的每一位是否需要改变(使用异或操作),行列交叉处改变2次,相当于没有发生改变。
第三步,计算得到若反转之后,共有多少个'w'。
代码如下:
#include <stdio.h>
#include <string.h>
//一个N*N的方格,用来存放'b' or 'w'
unsigned char field[1001][1001];
//一个N*N的方格,用来标记对应的field数组.若flag[i][j]为1,则要反转,
//即将field[i][j]中的字符由'b'改为'w'或者'w'改为'b';若flag[i][j]为0,
//则无需改变.
unsigned char flag[1001][1001];
int main()
{
int i,j,n,num,count=0,testcase,k,q,x,y;
//col数组用来记录field的列是否需要变化;row数组用来记录field的行是否需要变化
unsigned char col[1001],row[1001];
scanf("%d",&testcase);
while(testcase--)
{
memset(flag,0,sizeof(flag));
memset(col,0,sizeof(col));
memset(row,0,sizeof(row));
num = 0;
count++;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%s",field[i]);
scanf("%d",&q);
//产生row和col数组的结果
for(i=0;i<q;i++)
{
scanf("%d %d",&x,&y);
x = x-1;
y = y-1;
row[x] = row[x]^1;
col[y] = col[y]^1;
}
//对flag数组进行操作,得到最终形成的0 1矩阵
for(i=0;i<n;i++)
{
for(k=0;k<n;k++)
flag[i][k] = flag[i][k]^row[i];
for(k=0;k<n;k++)
flag[k][i] = flag[k][i]^col[i];
}
//根据flag数组,结合field数组,求得最终的'w'个数
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if((field[i][j] == 'w' && flag[i][j] == 0)||(field[i][j] == 'b' && flag[i][j] == 1))
num++;
}
printf("Case #%d: %d\n",count,num);
}
return 0;
}