蓝桥杯第八届个人决赛:生命游戏

标题:生命游戏

康威生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
这个游戏在一个无限大的2D网格上进行。

初始时,每个小方格中居住着一个活着或死了的细胞。
下一时刻每个细胞的状态都由它周围八个格子的细胞状态决定。

具体来说:

  1. 当前细胞为存活状态时,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
  2. 当前细胞为存活状态时,当周围有2个或3个存活细胞时, 该细胞保持原样。
  3. 当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
  4. 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。 (模拟繁殖)

当前代所有细胞同时被以上规则处理后, 可以得到下一代细胞图。按规则继续处理这一代的细胞图,可以得到再下一代的细胞图,周而复始。

例如假设初始是:(X代表活细胞,.代表死细胞)


.XXX.

下一代会变为:

…X…
…X…
…X…

康威生命游戏中会出现一些有趣的模式。例如稳定不变的模式:


.XX.
.XX.

还有会循环的模式:

… … …
.XX… .XX… .XX…
.XX… .X… .XX…
…XX. -> …X. -> …XX.
…XX. …XX. …XX.
… … …

本题中我们要讨论的是一个非常特殊的模式,被称作"Gosper glider gun":


…X…
…X.X…
…XX…XX…XX.
…X…X…XX…XX.
.XX…X…X…XX…
.XX…X…X.XX…X.X…
…X…X…X…
…X…X…
…XX…

假设以上初始状态是第0代,请问第1000000000(十亿)代一共有多少活着的细胞?

注意:我们假定细胞机在无限的2D网格上推演,并非只有题目中画出的那点空间。
当然,对于遥远的位置,其初始状态一概为死细胞。

注意:需要提交的是一个整数,不要填写多余内容。

package eighthCompetition;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.LinkedList;

public class LifeGame
{
	/*
	 * 思路如此:先构建出这样的一个棋盘,然后在上面模拟这样的生命游戏
	 */
	
	//构造边长为888的正方形地图,和一个同样大小的临时地图,
	//因为需要在一张地图上做更替,然后另一张地图进行保存
	//第三张地图表示某个点是否被访问过
	public static int SIZE=888;
	public static int[][] map=new int[SIZE][SIZE];
	public static int[][] tempmap=new int[SIZE][SIZE];
	public static int[][] ischenk=new int[SIZE][SIZE];
	
	//构造一个表示坐标的内部类
	public static class Position
	{
		public int x;
		public int y;
		public Position(int x,int y)
		{
			this.x=x;
			this.y=y;
		}
	}
	
	//构造一个表示一个点的附近的八个点的位置,这里用二维数组表示
	public static int[][] around = {{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};
	
	//构造一个链表保存当前活着的细胞,每一次更新一代就是遍历这个链表,
	//遍历里面的每一个活着的细胞,然后从链表中删除旧的细胞,增加新的细胞
	public static LinkedList<Position> life=new LinkedList<Position>();
	
	//将这个游戏转换成棋盘上的数字模型
	public static void GetMap() throws Exception
	{
		BufferedReader in=new BufferedReader(new FileReader(new File("src/eighthCompetition/jane.txt")));
		//为了将这个本来存在的几十个生命尽量放在地图的中间,所以设置一个边距
		int margin=444;
		String str=null;
		int y=0;
		while((str=in.readLine())!=null)
		{
			for (int x = 0; x < str.length(); x++)
			{
				if((str.charAt(x))=='X')
				{
					map[x+margin][y+margin]=1;
					life.addLast(new Position(x+margin, y+margin));
				}
			}
			y++;
		}
		in.close();
	}
	
	//判断这个位置活着的细胞的去留,题目描述得很清晰,就是活着得细胞身边有两个或者三个活着的细胞才能活着
	//否则死去,死去得细胞身边有三个活着得细胞才能变成活着的,
	//所以判断死的细胞能否变成活着就只是看一下活着的细胞的旁边的就行了
	public static void judge(Position p)
	{
		//这个是计数这个细胞的周围活着的细胞有多少个
		int count1=0;
		for (int i = 0; i < around.length; i++)
		{
			if(map[p.x+around[i][0]][p.y+around[i][1]]==1)
			{
				count1++;
			}
			else
			{
				//现在是活着的旁边这个细胞是死的,判断它能否活着
				//如果这个细胞没有被判断过是否可以变成活着的,就行判断
				if(ischenk[p.x+around[i][0]][p.y+around[i][1]]==0)
				{
					//先保存这个死细胞的位置,还有记录它旁边活着的细胞的个数
					int DeathX=p.x+around[i][0];
					int DeathY=p.y+around[i][1];
					int count2=0;
					
					//然后遍历它的旁边的八个位置的活着的细胞的个数
					for (int j = 0; j < around.length; j++)
					{
						if(map[DeathX+around[j][0]][DeathY+around[j][1]]==1)
						{
							count2++;
						}
					}
					
					//如果活着的细胞刚好是3个,就将这个细胞复活,将临时地图修改,并且将这个细胞加入下一代的life中
					if(count2==3)
					{
						tempmap[DeathX][DeathY]=1;
						life.addLast(new Position(DeathX, DeathY));
					}
					ischenk[DeathX][DeathY]=1;
				}
			}
		}
		//当遍历完周围八个位置后,看活着的细胞是否是两个或者三个
		if(count1==2||count1==3)
		{
			tempmap[p.x][p.y]=1;
			life.addLast(p);
		}
	}
	
	public static void main(String[] args) throws Exception
	{
		//先构造这样的地图
		GetMap();
		//我们先遍历80代
		for (int i = 0; i < 80; i++)
		{
			//每一代将临时地图更新,将是否检查的地图更新,将或者的细胞life更新
			tempmap=new int[SIZE][SIZE];
			ischenk=new int[SIZE][SIZE];
			int lives=life.size();
			System.out.print(lives+"  ");
			for(int x=0;x<lives;x++)
			{
				judge(life.getFirst());
				life.removeFirst();
			}
			map=tempmap;
		}
	}
}
/*
 * 36	原始的数目
 * 
 * 39  43  48  51  44  51  48  61  42  48  50  54  55  56  42  44  47  53  54  54  54  49  60  43  50  47  47  50  48  41  
 * 
 * 44  48  53  56  49  56  53  66  47  53  55  59  60  61  47  49  52  58  59  59  59  54  65  48  55  52  52  55  53  46  
 * 
 * 49  53  58  61  54  61  58  71  52  58  60  64  65  66  52  54  57  63  64 
 * 
 * 通过上面就会发现,每过30代,细胞的数目就会增加5个
 */

这题是看了某一篇博客写出来的,若有侵权请告知
发布了133 篇原创文章 · 获赞 37 · 访问量 4755

猜你喜欢

转载自blog.csdn.net/qq_43416157/article/details/104122300