根据百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
根据当前状态,写一个函数来计算面板上所有细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。
示例:
输入:
[
[0,1,0],
[0,0,1],
[1,1,1],
[0,0,0]
]
输出:
[
[0,0,0],
[1,0,1],
[0,1,1],
[0,1,0]
]
分析:
要注意的是,细胞的状态是同时变化的,不能在一个数组里从第一个开始遍历,这样的话前面的结果会影响到后面细胞的状态。所以一个很自然的想法就是额外开辟一个数组记录当前细胞的状态,当然这样是很浪费空间的。也可以像官方题解中那样,定义“2”这种状态。这里采取另一种方式,因为int可以存储更多的比特位,我们用最后一位表示当前的状态(1表示活细胞,0表示死细胞),倒数第二位表示下一个状态,将每个细胞遍历完之后,再统一移位。
class Solution {
public:
void gameOfLife(vector<vector<int>>& board) {
int dx[8] = {0, 0, 1, -1, 1, 1, -1, -1};
int dy[8] = {1, -1, 0, 0, 1, -1, 1, -1};
if(board.size() == 0) return;
const int n = board.size();
const int m = board[0].size();
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
int cnt = 0;
for(int k = 0; k < 8; k++){
int xx = i + dx[k];
int yy = j + dy[k];
if(xx < 0 || xx >= n || yy < 0 || yy >= m) continue;
cnt += board[xx][yy] & 1;
}
if((board[i][j] & 1) > 0){
//该位置是活细胞
if(cnt >= 2 && cnt <= 3) board[i][j] = 0b11;
//原来的值是01,其他情况下一状态为死细胞
}else if(cnt == 3){
board[i][j] = 0b10;
}
}
}
//移位之后要么是00,要么是01
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
board[i][j] >>= 1;
}
};
218

被折叠的 条评论
为什么被折叠?



