[计蒜客]A1537 The Game of Life

题目链接:The Game of Life

题目大意:

一个无限大的平面网格上有一堆点,初始只分布在3*5的区域里面。

经过321次传递,每次传递遵从以下规则。

1.如果一个点是1,并且周围3*3的去心区域中有2或者3个1,那么这个点保留,否则去除。

2.如果一个点是0,并且周围3*3的去心区域中有3个1,那么这个点变成1。

询问每一次传递后有多少个1。

 

看着就像模拟,因为实在没啥规律,考虑每次最多向外传递一格,于是理论上642*642的方阵就够用了。

写了个暴力更新,于是愉快地T了。

后来发现其实到一定程度了就往外传递不了了,于是改成100*100,还是T了。

写了好久不知道咋做,只能去看提交列表里面的大哥做法。

 

看完直呼妙啊。

考虑邻接矩阵和邻接表的关系。

642*642的矩阵可以看成是邻接矩阵,但是这个范围实在是太大了,而且又很多0元素。

于是我们可以存储离散点,就类似于邻接表了,每次遍历的范围从坐标范围相关改成离散点个数相关,又因为有很多0元素,其实离散点个数很少。

就可以大幅度减小时间和空间占用了。

 

用一个vector存储当前在图上的点,对于每个点,在每次更新时都将它周围8个点丢到tmp数组中,排序去重,算出每个相同坐标重复的个数,就可以进行更新了。

当然还要储存每个点是否为1,这可以用map做到。

具体实现看代码

 1 #include <bits/stdc++.h>
 2 #define pii pair<int, int>
 3 #define Mid ((l + r) / 2)
 4 #define lson (rt << 1)
 5 #define rson (rt << 1 | 1)
 6 using namespace std;
 7 int read() {
 8     char c; int num, f = 1;
 9     while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
10     while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
11     return f * num;
12 }
13 int n, m;
14 vector<pii> vis, g, tmp;
15 map<pii, int> tt;
16 void evl() {
17     vis.clear(); tmp.clear();
18     tt.clear();
19     for(auto &t : g) {
20         tt[t] = 1;
21         for(int i = -1; i <= 1; i++) {
22             for(int j = -1; j <= 1; j++) if(i || j) {
23                 vis.push_back({t.first + i, t.second + j});
24             }
25         }
26     }
27     sort(vis.begin(), vis.end());
28     for(int i = 0; i < vis.size(); i++) {
29         int k = 1;
30         while(i + k < vis.size() && vis[i + k] == vis[i + k - 1])k++;
31         if(k == 3 || (k == 2 && tt[vis[i]])) tmp.push_back({vis[i].first, vis[i].second});
32         i = i + k - 1;
33     }
34     g = tmp;
35 }
36 void work() {
37     n = read(); m = read();
38     g.clear();
39     for(int i = 1; i <= n; i++) {
40         char s[10];
41         scanf("%s", s + 1);
42         for(int j = 1; j <= m; j++) {
43             if(s[j] == '#') 
44                 g.push_back({i, j});
45         }
46     }
47     int k = 0, tmp = g.size();
48     for(int qwq = 1; qwq <= 321; qwq++) {
49         evl();
50         if((int)g.size() > tmp) {
51             tmp = g.size();
52             k = qwq;
53         }
54     }
55     printf("%d %d %d\n", k, tmp, (int)g.size());
56 }
57 signed main()
58 {
59     int Case = read();
60     while(Case--) work();
61     return 0;
62 }
View Code

 

posted @ 2021-04-30 12:27  _onglu  阅读(61)  评论(0编辑  收藏  举报