HDU4146 Flip Game

题目链接

分析:

这题是比赛的题,当时没做出来。后来看了一下题解明白了。

首先看一下异或:

对一行(列)改变奇数次,相当于改变了一次,改变偶数次,相当于没改变。

用flag数组来标记最后的结果,即改没改变。

还有一个问题,对于(xi,yi)要改变两次(即相当于没改变),当每次操作时,对所在行改变一次,对所在列改变一次,那么行列的交叉点(xi,yi)也就相当于没改变,符合题意。

还有flag关于异或的问题。

当前的flag只有两个值,即0,1

当0异或1时,结果为1,也就是说要改变;当0异或0时,结果为0,也就是说不要改变;等等等等。

最后一个问题:发现当把标记数组定义为int时是会超时的。但是用unsigned char或者是char却不会。

AC(代码)如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 1010

char G[MAXN][MAXN];
unsigned char row[MAXN], col[MAXN], flag[MAXN][MAXN];

int main(){
    int n, i, T, q, nCase=0, x, y, j, cnt;

    scanf("%d", &T);
    while(T--){
        nCase++;
        cnt = 0;

        scanf("%d", &n);

        memset(row, 0, sizeof(row));
        memset(col, 0, sizeof(col));
        memset(flag, 0, sizeof(flag));

        for(i=0; i<n; i++) scanf("%s", G[i]);

        scanf("%d", &q);
        while(q--){
            scanf("%d %d", &x, &y);
            x--; y--;
            row[x] ^= 1;
            col[y] ^= 1;
        }

        for(i=0; i<n; i++){
            for(j=0; j<n; j++) flag[i][j] ^= row[i];
            for(j=0; j<n; j++) flag[j][i] ^= col[i];
        }

        for(i=0; i<n; i++){
            for(j=0; j<n; j++){
                if((G[i][j] == 'w' && flag[i][j] == 0) || (G[i][j] == 'b' && flag[i][j] == 1))
                    cnt++;
            }
        }
        printf("Case #%d: %d\n", nCase, cnt);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/tanhehe/p/2953138.html