二哥养细菌

http://acm.sjtu.edu.cn/OnlineJudge/problem/1003


题目描述

二哥不仅种苹果和花生,还养了很多细菌。二哥的细菌培养皿成方格形,边长为L。长期培养后,二哥发现了细菌繁殖的规律:最初每个格子里的细菌及其后代都会独立繁殖,每次繁殖都会在其上下左右四个相邻的格子里产生新的细菌,而已经存在的细菌在培养皿充满细菌之前都不会死亡。另外,有一些格子里可能还有抗生素,细菌在有抗生素的格子里无法繁殖。

二哥于是发明了一个游戏:取一个新的培养皿,在某些格子里放入细菌或抗生素,然后观察细菌不断繁殖直至充满整个培养皿的所有没有抗生素的格子。不过二哥已经对这个游戏厌烦了,他现在只想知道经过多少轮繁殖后,细菌会充满整个培养皿(不算有抗生素的格子)。

输入格式

第1行有1个整数,边长L。

第2行至第L+1行,每行有L个整数,取值为0、1或2。0表示格子里最初没有细菌,1表示格子里最初有细菌,2表示格子里最初有抗生素。

输出格式

输出一个整数m,表示经过m轮繁殖后,细菌会充满整个培养皿(不算有抗生素的格子)

说明

【样例解释】 第一轮繁殖:

2 1 0

1 1 1

0 1 0

第二轮繁殖:

2 1 1

1 1 1

1 1 1

【数据范围】

对于全部数据:1L100 ,保证最终能够充满培养皿(不算有抗生素的格子)。

Sample Input

3
2 0 0
0 1 0
0 0 0

Sample Output

2


      如果是在每次遍历的过程中,当元素值为1时,其上下左右的元素值如果为0的话,则设相应的位置的元素值为1,直到遍历时没有元素值改变时,表示细菌已经充满器皿。这种方法的时间复杂度大,因为它在整个遍历的过程中会重复遍历已经遍历过的且其上下左右都是为1元素值,这样的已遍历的元素的数量会随着遍历次数的增加而增大。


      那么我们怎样来减少元素的重复遍历呢?

      可不可以在每次遍历的过程中,确定下一次需要遍历的元素的位置保存下来,那么下次只要对这些保存下来的元素遍历就可以了,如此迭代直到没有需要遍历的元素时细菌充满器皿。

这是可以的。

      在每次遍历中,当元素的值为1时,如果其相应的上下左右的值为0时,则将其相应上下左右的元素的坐标记录在一个数组里,即数组中保存了在本次遍历中从0变为1的元素,也就是下次遍历的元素的位置。

      那么这个数组的历次遍历中存储的元素数量总数小于等于L^2,因为器皿中有的位置可能放抗生素。即每个元素最多只遍历了一次,从而大大降低的时间复杂度。



代码如下:

#include 
#include 
using namespace std;


int main()
{
	int L;  //方形器皿边长
	cin>>L;
	int **p = new int*[L];     //二维指针
	int *x = new int[L*L];     //存放遍历中值为1的元素的横坐标
	int *y = new int[L*L];     //存放遍历中值为1的元素的纵坐标
	int *n_x = new int[L*L];   //存放下一次遍历中值为1的元素的横坐标
	int *n_y = new int[L*L];   //存放下一次遍历中值为1的元素的横坐标
	int top = 0;     //本次需要遍历的元素数
	int n_top = 0;   //下次需要遍历的元素数
	int m = 0; //记录繁殖次数

	int i = 0, j = 0;
	for(i = 0; i < L; i++)     //申请一个二维数组的内存
	{
		p[i] = new int[L];
	}

	for(i = 0; i < L; i++)
	{
		for(j = 0; j < L; j++)
		{
			cin>>p[i][j];
			if(1 == p[i][j])
			{
				x[top] = i;
				y[top] = j;
				top++;
			}
		}
	}
	
	const int d[][2] = {{-1,0}, {0,-1}, {1,0}, {0,1}};
	while(1)
	{
		for(i = 0; i < top; i++)
		{
			for(j = 0 ; j < 4; j++)
			{
				int x1 = x[i]+d[j][0];
				int y1 = y[i]+d[j][1];
				

				if( 0 > x1 || x1 >= L || 0 > y1 || y1 >=L)			
					continue;
								
				if(0 == p[x1][y1])
				{
					n_x[n_top] = x1;      //记录下一次要遍历的元素的横、纵坐标。
					n_y[n_top] = y1;      
					n_top++;
					p[x1][y1] = 1;
				}
			}
		}
		
		if(n_top == 0) break;
		for(i = 0; i

 时间:30ms / 内存:47952kb


参考:http://www.cnblogs.com/txd0u/p/3352328.html    

这篇文章使用静态数组,运行时间更快一些,但其事先定义较大的静态数组来容纳元素,空间复杂度相比本文的用动态数组的方法大。


你可能感兴趣的:(ACM,二哥养细菌,生长,二维数组,指针,算法)