Codeforces Round #641 Div1.C Orac and Game of Life 中文题解

Caro23333

2020-04-30 00:26:59

Personal

### Orac and Game of Life 中文题解 称一个方格 $(i,j)$ 是好的,当且仅当至少有一个与 $(i,j)$ 相邻的方格颜色与 $(i,j)$ 相同。则经过一个回合后,好方格的颜色改变而不好的方格的颜色不变。 如果所有方格都是不好的,那么所有方格的颜色都始终不变。 显然,一个好方格 $(i,j)$ 以后不会变成不好的方格。 对于一个不好的方格 $(i,j)$,如果有至少一个好的方格 $(i',j')$ 与之相邻,由于 $(i,j)$ 不好,所以 $(i,j)$ 与 $(i',j')$ 颜色不同,在一个回合后,$(i,j)$ 的颜色不变而 $(i',j')$ 的颜色改变,于是 $(i,j)$ 变成了好的;反之,如果与 $(i,j)$ 相邻的方格都是不好的,在一个回合后,$(i,j)$ 以及与 $(i,j)$ 相邻的方格颜色都不变,因此 $(i,j)$ 仍然是不好的。 因此,对于一个方格 $(i,j)$, $(i,j)$ 第一次成为好方格的所需要的回合数 $f_{i,j}$ 等于 $(i,j)$ 到达一个好方格的最短曼哈顿距离。于是,可以通过BFS求出 $f_{i,j}$。 注意到,对于 $k \le f_{i,j}$,在第 $k$ 个回合中, $(i,j)$ 的颜色不变;对于 $k>f_{i,j}$,在第 $k$ 个回合中,$(i,j)$ 的颜色变化。于是可以 $O(1)$ 回答每个询问,总复杂度 $O(nm+t)$ 。 Problem and Tutorial by AKEE 谨以此题献 **John Horton Conway**,一位值得我们铭记的数学家。愿您安息。 ```cpp #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define pii pair<int,int> #define mp make_pair #define fi first #define se second using namespace std; typedef long long ll; const int MAXN = 1005; inline ll readint() { ll res = 0, f = 1; char c = 0; while(!isdigit(c)) { c = getchar(); if(c=='-') f = -1; } while(isdigit(c)) res = res*10+c-'0', c = getchar(); return res*f; } int n,m,T,a[MAXN][MAXN]; char str[MAXN]; int f[MAXN][MAXN],pos[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; bool vis[MAXN][MAXN]; inline bool check(int x, int y) { for(int i = 0; i<4; i++) { int nx = x+pos[i][0], ny = y+pos[i][1]; if(a[nx][ny]==a[x][y]) return true; } return false; } pii q[MAXN*MAXN]; inline void bfs() { int front = 0, rear = 0; for(int i = 1; i<=n; i++) for(int j = 1; j<=m; j++) if(check(i,j)) f[i][j] = 0, vis[i][j] = true, q[rear++] = mp(i,j); while(front<rear) { pii now = q[front++]; for(int i = 0; i<4; i++) { int nx = now.fi+pos[i][0], ny = now.se+pos[i][1]; if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny]) continue; f[nx][ny] = f[now.fi][now.se]+1; vis[nx][ny] = true; q[rear++] = mp(nx,ny); } } } int main() { n = readint(), m = readint(), T = readint(); memset(a,-1,sizeof(a)); for(int i = 1; i<=n; i++) { scanf("%s",str+1); for(int j = 1; j<=m; j++) a[i][j] = str[j]-'0'; } bfs(); int x,y; ll t; while(T--) { x = readint(), y = readint(), t = readint(); if(vis[x][y]) printf("%d\n",a[x][y]^(max(0ll,t-f[x][y])&1)); else printf("%d\n",a[x][y]); } return 0; } ```