【CF1349C Orac and Game of Life】题解
题目链接
题目
- 给定第 个时刻的 的 矩阵。
- 每过一个时刻, 矩阵都会发生如下的变化:
- 考虑第 行第 列的格子。若其上下左右四个方向中相邻的格子存在与其数字相同的格子,则此格子在下一个时刻会变成另一个数字( 变 , 变 )。
- 有 次询问。每次询问你在第 个时刻第 行第 列的格子上的数字是什么。
- ,,,,。
Please notice the unusual memory limit of this problem.
Orac likes games. Recently he came up with the new game, "Game of Life".
You should play this game on a black and white grid with rows and columns. Each cell is either black or white.
For each iteration of the game (the initial iteration is ), the color of each cell will change under the following rules:
- If there are no adjacent cells with the same color as this cell on the current iteration, the color of it on the next iteration will be the same.
- Otherwise, the color of the cell on the next iteration will be different.
Two cells are adjacent if they have a mutual edge.
Now Orac has set an initial situation, and he wants to know for the cell (in -th row and -th column), what will be its color at the iteration . He may ask you these questions several times.
思路
我们思考,假设存在一个格子能变色,则它一直能变色,因为它旁边必然存在一个格子与它颜色始终相同。
再思考,假如一个格子能变色,它旁边的一个格子不能变色,那么再第一个格子第一次变色后,第二个格子也能变色。因为第一个格子变色后颜色就与第二个格子相同了。
综上所述,我们可以发现变色存在传染性。
因此,我们可以把初始棋盘中能变色的时间戳记为0,然后用广搜把所有格子开始变色的时间戳都求出来。
这个过程中要注意的是:
- 初始棋盘有可能所有格子都不变色
- 若询问时间小于开始变色时间,应输出初始颜色
总时间复杂度:
代码
// Problem: CF1349C Orac and Game of Life
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1349C
// Memory Limit: 125 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
#define N 1010
struct node
{
int x, y;
}t, tt;
int n, m, i, j, k, T;
int dx[4]={0, 0, 1, -1};
int dy[4]={1, -1, 0, 0};
int x, y, newx, newy;
int a[N][N], Q;
char s[N][N];
queue<node>q;
int check(int x, int y)
{
if(s[x-1][y]==s[x][y]) return 1;
if(s[x][y-1]==s[x][y]) return 1;
if(s[x+1][y]==s[x][y]) return 1;
if(s[x][y+1]==s[x][y]) return 1;
return 0;
}
signed main()
{
// freopen("tiaoshi.in", "r", stdin);
// freopen("tiaoshi.out", "w", stdout);
n=read(); m=read(); Q=read();
for(i=1; i<=n; ++i) scanf("%s", s[i]+1);
for(i=1; i<=n; ++i)
for(j=1; j<=m; ++j)
if(check(i, j))
a[i][j]=1, t.x=i, t.y=j, q.push(t);
// for(i=1; i<=n; ++i, printf("\n"))
// for(j=1; j<=m; ++j)
// printf("%d ", a[i][j]);
while(!q.empty())
{
t=q.front(); q.pop();
for(i=0; i<4; ++i)
{
newx=t.x+dx[i];
newy=t.y+dy[i];
if(newx<1 || newy<1 || newx>n || newy>m) continue;
if(a[newx][newy]) continue;
a[newx][newy]=a[t.x][t.y]+1;
// printf("a[%d][%d]=%d\n", newx, newy, a[newx][newy]);
tt.x=newx; tt.y=newy;
q.push(tt);
}
}
// for(i=1; i<=n; ++i, printf("\n"))
// for(j=1; j<=m; ++j)
// printf("%d ", a[i][j]);
while(Q--)
{
x=read(); y=read(); T=read();
if(!a[x][y] || T<a[x][y]) printf("%c\n", s[x][y]);
/*
变了 T-(x-1) 次
*/
else printf("%lld\n", ((s[x][y]-'0')^((T-a[x][y]+1)&1)));
// printf("%d %d\n", (s[x][y]-'0'), ((T-a[x][y]+1)&1));
}
return 0;
}
总结
这道题解题的关键在于发现格子存在传染性。
发现的过程主要是通过模拟和分类讨论实现的。
同理,这类题可以尝试去模拟样例,分类讨论,求出关键性质。
本文来自博客园,作者:zhangtingxi,转载请注明原文链接:https://www.cnblogs.com/zhangtingxi/p/16297018.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!