2017 NanNing ICPC H. The Game of Life (思维题)

原题地址:https://nanti.jisuanke.com/t/19974

原帖地址:https://blog.csdn.net/qq_36398723/article/details/7934899

思路:详见代码,就是直接模拟稍微加点思维就过了.

/*
主要思想:用一个point数组记录有细胞的格子,用一个tmp的数组记录某一个有细胞的格子的周围8个格子
然后如果一个格子周围有x个活细胞,把么这个格子就会在tmp中出现x次.那么这样子就很容易可以判断某一个
格子有几个格子.
但是这个有一个要注意的地方:就是如果一个活细胞周围没有别的活细胞,那么这个点其实是不会加入tmp数组的
所以需要对这个点进行特判能不能存活,(在这里很明显是不能的)
*/
#include <bits/stdc++.h>
#define Bounds 500
using namespace std;
const int L[] = {1, 0, -1, 0, 1, 1, -1, -1};
const int R[] = {0, 1, 0, -1, 1, -1, 1, -1};
const int MAXN = 1100;
struct Point {
    Point() {}
    Point(int _x, int _y) {
        x = _x;
        y = _y;
    }
    bool operator < (const Point& r)const {
        if (x != r.x) return x < r.x;
        return y < r.y;
    }
    bool operator == (const Point& r)const {
        return x == r.x && y == r.y;
    }
    bool operator != (const Point& r)const {
        return !(x == r.x && y == r.y);
    }
    int x, y;
} point[MAXN * MAXN], tmp[MAXN * MAXN * 8];
bool live[MAXN][MAXN];
//少于两个邻居会死
//邻居恰好为两个或者三个则生存下来
//三个以上则邻居死亡
//原先死的,恰好有三个邻居则生存
int unique_point(int n) {
    int temp = 0, ret = 0;
    while (temp < n) {
        int cnt = 1;
        while (temp + cnt < n && tmp[temp] == tmp[temp + cnt]) cnt++;
        if (cnt < 2) {//当前格子是活的,然后这一次之后会死
            live[tmp[temp].x + Bounds][tmp[temp].y + Bounds] = false;
        } else if (cnt == 2) {//当前格子是活的,然后这一次之后会活
            if (live[tmp[temp].x + Bounds][tmp[temp].y + Bounds])
                point[ret++] = Point(tmp[temp].x, tmp[temp].y);
        } else if (cnt == 3) {
            //周围有3个的活细胞的格子,那么无论这个是否是活的,在下一轮都是可以活的
            live[tmp[temp].x + Bounds][tmp[temp].y + Bounds] = true;
            point[ret++] = Point(tmp[temp].x, tmp[temp].y);
        } else {//周围活细胞大于等于4的情况,都是死的
            live[tmp[temp].x + Bounds][tmp[temp].y + Bounds] = false;
        }
        temp += cnt;
    }
    return ret;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        memset(live, false, sizeof(live));
        int n, m;
        scanf("%d%d", &n, &m);
        int tot = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) {
                char flag;
                cin >> flag;
                if (flag == '#') {
                    point[tot++] = Point(i, j);
                    live[i + Bounds][j + Bounds] = true;
                }
            }
        int starttime = 0, maxpeople = tot;
        for (int i = 1; i <= 321; i++) {
            int sum = 0;
            for (int j = 0; j < tot; j++)
                for (int k = 0; k < 8; k++) {
                    int x = point[j].x + L[k];
                    int y = point[j].y + R[k];
                    tmp[sum++] = Point(x, y);
                }
            sort(tmp, tmp + sum);
            for (int j = 0; j < tot; j++) {
                if (*lower_bound(tmp, tmp + sum, point[j]) != point[j]) {//特判周围没有任何一个活的细胞
                    live[point[j].x + Bounds][point[j].y + Bounds] = false;
                }
            }
            tot = unique_point(sum);
            if (tot > maxpeople) {
                maxpeople = tot;
                starttime = i;
            }
            if (tot == 0) break;
        }
        printf("%d %d %d\n", starttime, maxpeople, tot);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/82817705