描述
在细菌培养皿中,有一种病菌每天向四周扩散,遵循着以下的规律:
1、把细菌培养皿看成一个a行b列的二维数组;
2、初始状态下有m个病菌,每个病菌占据培养皿中的一格位置;
3、在无干扰情况下,每个病菌每天都会在其上下左右四格各复制一份病菌,且自己死亡;但如果多个病菌同时想向某一个复制自身,则会因为缺乏资源而都无法复制成功;无法向目前已有病菌的位置复制自身;病菌只能在培养皿中生存。
问:经过c天之后培养皿中的病菌分布情况是什么样子?
输入
一个正整数n,表示有n组案例(n<=10)。
每组案例先是四个正整数a、b、c、m,具体含义见【描述】。(a<=50, b<=50, c<=50, m<=100)
然后是m行数据,每行数据由两个整数xi和yi构成,表示第i个病菌所在的行和列(1<=xi<=a, 1<=yi<=b)。
输出
针对每组案例,输出a行b列由字符组成的阵列,表示第c天结束后培养皿中病菌的分布情况,其中X表示该位置没有病菌,O表示该位置有病菌。(注意是大写字母X和O,不是数字0)
每组案例的最后一行字符数据输出完后都要输出换行符。
样例输入
2
4 4 3 1
1 1
5 3 1 2
2 2
3 2
样例输出
XOXO
OXOX
XOXX
OXXX
XOX
OXO
OXO
XOX
XXX
HINT
第一组案例中,初始化分布为
OXXX
XXXX
XXXX
XXXX
第一天结束后为
XOXX
OXXX
XXXX
XXXX
第二天结束后为
XXOX
XXXX
OXXX
XXXX
其中(1,1)和(2,2)位置都因为有多个病菌同时想要向其中复制自身而无法生成病菌
第三天结束后为
XOXO
OXOX
XOXX
OXXX
第二组案例中,初始化分布为
XXX
XOX
XOX
XXX
XXX
第一天结束后为
XOX
OXO
OXO``
XOX
XXX
我的代码:
#include<iostream>
using namespace std;
void f(int** a, int x, int y)
{
a[x][y]--;
a[x - 1][y]++;
a[x + 1][y]++;
a[x][y - 1]++;
a[x][y + 1]++;
}
int main()
{
int n;
cin >> n;
while (n--)
{
int a, b, c, m;
cin >> a >> b >> c >> m;
int** sta = new int* [a + 2];
int** stb = new int* [a + 2];
for (int i = 0; i <= a+1; i++)
{
sta[i] = new int[b + 2];
stb[i] = new int[b + 2];
}
for (int i = 0; i <= a+1; i++)
{
for (int j = 0; j <= b+1; j++)
{
sta[i][j] = 0;//0表示没染色
stb[i][j] = 0;
}
}
while (m--)
{
int x, y;
cin >> x >> y;
stb[x][y] = 1;
//根据stb来改变sta,1表示染色一次
}
for (int k = 0; k < c; k++)//经过c天的变化
{
for (int i = 1; i <= a ; i++)
{
for (int j = 1; j <= b ; j++)
{
if (stb[i][j] == 1)
{
f(sta, i, j);
}
}
}
for (int i = 0; i <= a+1; i++)
{
for (int j = 0; j <= b+1; j++)
{
stb[i][j] = sta[i][j];
sta[i][j] = 0;
}
}
}
for (int i = 1; i <= a; i++)
{
for (int j = 1; j <= b; j++)
{
if (stb[i][j] == 1)
{
cout << "O";
}
else
{
cout << "X";
}
}
cout << endl;
}
}
return 0;
}
思路总结:
1.因为病菌是向四周复制,所以这里使用了一种巧妙的方法:即在最外面多围一圈,如此一来,不用担心数组越界,同时避免了分情况讨论的繁琐;
2.由于每一天要将所有的病毒同时复制,而不能存在先后之别,所以我额外定义了数组stb,其作用是作为病毒复制的“依据”。即病毒的复制是根据stb数组中病毒的分布来改变sta数组的,而stb并不会受到影响。在sta复制完成之后,再将sta复制给stb,同时清空sta;最终经过c天的循环,统计所有为1的格子,也就是只复制一次的格子为病毒,完成。