zoukankan      html  css  js  c++  java
  • 289. Game of Life

    一、题目

      1、审题

        

      2、分析

        编程实现  “LIFE” 这个游戏:

          ①、若 m 的周围8个邻居细胞中存活的细胞数 < 2,则此细胞从存活状态变为死亡状态;

          ②、若 m 的周围8个邻居细胞中存活的细胞数 = 2 或 = 3,则此细胞从存活状态变为存活状态;

          ③、若 m 的周围8个邻居细胞中存活的细胞数 > 3,则此细胞从存活状态变为死亡状态;

          ③、若 m 的周围8个邻居细胞中存活的细胞数 = 3,则此细胞从死亡状态变为存活状态;  

        只能一次性更新所有的细胞的状态,不能用改变后的状态来判断后边的细胞的状态。

        其中 1代表存活状态,0 代表死亡状态。

    二、解答

      1、思路

       方法一、

      

       ①、采用两个 bit 位来表示状态。刚开始,所有细胞全部是 00 或者 01;

       ②、注意状态 1 与状态 2 是独立的。

       ③、所有的细胞是同时从状态 1 变为状态 2的。

       ④、计算所有细胞在未变化之前的所有邻居细胞的状态,并记录此细胞将要变化的状态2。

       ⑤、因为状态 2 默认为 0,即死亡状态,故不需要考虑状态转变: 01 --> 00

       ⑥、最终,通过  >> 1 向右移动一位,删除所有细胞的状态 1.

       ⑦、每一个细胞的状态 2 的计算方法:

          01 --> 11: 当 board == 1 并且 2 <= lives && lives <= 3;

          00 --> 10: 当 board == 0 并且 lives == 3。

       ⑧、获取当前的细胞的状态:  board[i][j] & 1

       ⑨、获取细胞将要变化的状态: board[i][j] >> 1

     1     public void gameOfLife(int[][] board) {
     2         if(board == null || board.length == 0)
     3             return;
     4         int m = board.length, n = board[0].length;
     5         
     6          // In the beginning, every 2nd bit is 0;
     7         // So we only need to care about when will the 2nd bit become 1.
     8         for(int i = 0; i < m; i++) {
     9             for (int j = 0; j < n; j++) {
    10                 int lives = liveNeighbors(board, m, n, i, j);
    11                 if(board[i][j] == 1 && 2 <= lives && lives <= 3)
    12                     board[i][j] = 3;    // Make the 2nd bit 1: 01 ---> 11
    13                 if(board[i][j] == 0 && lives == 3)
    14                     board[i][j] = 2;    // Make the 2nd bit 1: 00 ---> 10
    15             }
    16         }
    17         
    18         for(int i = 0; i < m; i++)
    19             for (int j = 0; j < n; j++) 
    20                 board[i][j] >>= 1;
    21     }
    22     
    23     private int liveNeighbors(int[][] board, int m, int n, int i, int j) {
    24         int lives = 0;
    25         for(int x = Math.max(i - 1, 0); x <= Math.min(i + 1, m - 1); x++) {
    26             for (int y = Math.max(j - 1, 0); y <= Math.min(j + 1, n - 1); y++) {
    27                 lives += board[x][y] & 1;
    28             }
    29         }
    30         lives -= board[i][j] & 1;
    31         return lives;
    32     }

      方法二、

        可以通过值不是 0 和 1 的两个常量记录此细胞将要变化的状态。

        从而不影响统计出其他细胞的周围的存活细胞数。

        最终在循环给元素赋更新的值。

     1     int live = 3;
     2     int die = 2;
     3     public void gameOfLife2(int[][] board) {
     4         if(board == null || board.length == 0)
     5             return;
     6         int rows = board.length, cols = board[0].length;
     7         // we only flip the 1 to die and 0 to live
     8         // so when we find a die around, it must be a previous 1
     9         // then we can count the 1s without being affected
    10         for (int i = 0; i < rows; i++) {
    11             for (int j = 0; j < cols; j++) {
    12                 int around = countLive(i, j, board);
    13                 if(board[i][j] == 0 && around == 3)
    14                     board[i][j] = live;
    15                 else if(board[i][j] == 1) {
    16                     if(around == 2 || around == 3)
    17                         continue;
    18                     if(around < 2 || around > 3)
    19                         board[i][j] = die;
    20                 }
    21             }
    22         }
    23         for (int i=0;i<rows;i++){
    24             for (int j=0;j<cols;j++){
    25              if (board[i][j] == die)
    26                  board[i][j] = 0;
    27              if (board[i][j] == live)
    28                  board[i][j] = 1;
    29             }
    30         }
    31     }
    32     
    33     private int countLive(int i, int j, int[][] board) {
    34         int count = 0;
    35         int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
    36         
    37         for (int[] dir:dirs){
    38             int x = i+dir[0];
    39             int y = j+dir[1];
    40             
    41             if (x>=0 && y>=0 && x < board.length && y<board[0].length ){
    42                 
    43                 if (board[x][y] == 1 || board[x][y] == die)
    44                     count ++;
    45             }
    46         }
    47         
    48         return count;
    49     }
  • 相关阅读:
    [洛谷P3369] 普通平衡树 Treap & Splay
    [NOIp2016] 组合数问题
    [洛谷P4777] [模板] 扩展中国剩余定理
    [洛谷P3384] [模板] 树链剖分
    [NOIp2017] 时间复杂度
    [bzoj3270] 博物馆
    [USACO06DEC] Milk Patterns
    [USACO5.1] Musical Themes
    后缀数组 模板+详解
    [HNOI2004] L语言
  • 原文地址:https://www.cnblogs.com/skillking/p/10013886.html
Copyright © 2011-2022 走看看