zoukankan      html  css  js  c++  java
  • 「Codeforces 1349C」Orac and Game of Life

    Description

    给定一个 (n imes m) 的 01矩阵。当矩阵做一次迭代,所有单元格就行如下变换:

    • 如果一个单元格周围没有有一个与该格状态相同的单元格,那么这个单元格的状态不会改变。
    • 否则,(1 ightarrow 0, 0 ightarrow 1)

    如果两个单元格有邻边则相邻。

    现在一个叫 Orac 的睿智要问你 (t) 个问题:每次询问给定一个三元组 ((i, j, q)),表示在第 (i) 行第 (j) 列的位置,整个矩阵经过 (q) 次迭代后,的状态(0/1)。

    Hint

    • (1le n,mle 10^3)
    • (1le tle 10^5)
    • (1le qle 10^{18})

    Solution

    首先建图,将一个状态相同的连通块缩成一个点,记录一下这个点的大小 ( ext{size})。相邻的联通快就连边。

    然后可以发现,一次迭代之后,连通块会向外拓展一层。对于一个 ( ext{size} = 1) (在原图上表现为孤立的单元格)的结点来说,如果连通块尚未拓展到此处,那么它的状态将一直不变。

    于是,我们需要在新图上求出 每一个 ( ext{size} = 1) 的结点距与之最近的连通块的距离 ( ext{dis})

    要求出 ( ext{dis}),显然不可行的方法是枚举每一个 ( ext{size} = 1) 的点然后分别搜索或求 SSSP。

    但是我们可以倒着来——选出所有 ( ext{size}>1) 的结点来求,其实最终效果是一样的。

    但还是不能直接爆搜,这样会 Time limit exceeded on pretest 10。本蒟蒻用的方法是将所有这些点塞入队列,然后跑 spfa

    于是通过此题。

    Code

    /*
     * Author : _Wallace_
     * Source : https://www.cnblogs.com/-Wallace-/
     * Problem : Codeforces 1349C Orac and Game of Life
     */
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    const int N = 1e3 + 5;
    const int V = N * N;
    
    int n, m, t;
    char str[N][N];
    int bl[N][N];
    
    int node = 0;
    vector<int> G[V];
    bool statu[V];
    int size[V], dis[V];
    
    const int dx[] = {0, 0, -1, 1};
    const int dy[] = {-1, 1, 0, 0};
    void fill(int x, int y, int c) {
    	bl[x][y] = c, ++size[c];
    	char tmp = str[x][y];
    	for (register int i = 0; i < 4; i++) {
    		x += dx[i], y += dy[i];
    		if (x >= 1 && x <= n && y >= 1 && y <= m)
    			if (str[x][y] == tmp && !bl[x][y]) fill(x, y, c);
    		x -= dx[i], y -= dy[i];
    	}
    }
    
    bool inq[V];
    void initdis() { // 陈年spfa板子 
    	queue<int> Q;
    	for (register int i = 1; i <= node; i++)
    		if (size[i] > 1) Q.push(i), inq[i] = 1;
    	while(!Q.empty())
    	{
    		int cur=Q.front();  Q.pop();
    		inq[cur]=false;
    		for(register int i=0;i<G[cur].size();i++)
    		{
    			int nxt=G[cur][i],wei=dis[cur]+1;
    			if(wei<dis[nxt])
    			{
    				dis[nxt]=wei;
    				if(inq[nxt]) continue;
    				Q.push(nxt),inq[nxt]=true;
    			}
    		}
    	}
    }
    
    signed main() {
    	scanf("%d%d%d", &n, &m, &t);
    	for (register int i = 1; i <= n; i++)
    		scanf("%s", str[i] + 1);
    	
    	for (register int i = 1; i <= n; i++)
    		for (register int j = 1; j <= m; j++)
    			if (bl[i][j] == 0) fill(i, j, ++node);
    	
    	for (register int i = 1; i <= n; i++)
    		for (register int j = 1; j <= m; j++)
    			for (register int k = 0; k < 4; k++)
    				if (1 <= i + dx[k] && i + dx[k] <= n)
    					if (1 <= j + dy[k] && j + dy[k] <= m)
    						if (bl[i][j] != bl[i + dx[k]][j + dy[k]]) {
    							G[bl[i + dx[k]][j + dy[k]]].push_back(bl[i][j]);
    							G[bl[i][j]].push_back(bl[i + dx[k]][j + dy[k]]);
    						}
    	
    	for (register int i = 1; i <= node; i++) {
    		sort(G[i].begin(), G[i].end());
    		G[i].erase(unique(G[i].begin(), G[i].end()), G[i].end());
    	}
    	
    	memset(dis, 0x3f, sizeof dis);
    	for (register int i = 1; i <= node; i++)
    		if (size[i] > 1) dis[i] = 0;
    	initdis();
    	
    	while (t--) {
    		int x, y; long long q;
    		scanf("%d%d%lld", &x, &y, &q);
    		if (dis[bl[x][y]] == 0x3f3f3f3f) {
    			printf("%d
    ", str[x][y] - '0');
    			continue;
    		}
    		int ans = str[x][y] - '0';
    		ans ^= (max(0ll, q - dis[bl[x][y]]) & 1);
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    web自动化测试-D2-学习笔记之二(HTML基础之JS)
    web自动化测试-D2-学习笔记之一(HTML基础之DOM操作)
    web自动化测试-D1-学习笔记之一(HTML 和 CSS基础)
    Selenium-常问面试题
    python自动化测试-D11-学习笔记之一(yaml文件,ddt)
    python习题:封装一个日志模块
    python自动化测试-D10-学习笔记之二(Python–logging模块)
    python习题:unittest参数化-数据从文件或excel中读取
    python自动化测试-D10-学习笔记之一(unittest参数化)
    python自动化测试-D9-学习笔记之二(异常处理)
  • 原文地址:https://www.cnblogs.com/-Wallace-/p/12879674.html
Copyright © 2011-2022 走看看