题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
小蓝在一张无限大的特殊画布上作画。
这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。
小蓝在画布上首先点了一下几个点:(0, 0), (2020, 11), (11, 14), (2000, 2000) 。只有这几个格子上有黑色,其它位置都是白色的。
每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色(如果原来就是黑色,则还是黑色)。
请问,经过 2020 分钟后,画布上有多少个格子是黑色的。
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
解题思路
这是一道第十一届的蓝桥杯国赛题,是一道运用 BFS 广度优先搜索算法思想求解的题目,所处位置是第二道题,总体难度简单,接下来讲简单介绍求解思路。
首先转换坐标参照物,题目描述的坐标是按照数学二维坐标轴而言,需要转化为编程中二维数组的坐标。
从上图可以看出,由于 x 最小值为 -2020,但是二维数组下标不允许出现负数,故将数学二维坐标的坐标值进行平移操作,使得下标值不会出现负数即可。这里转化规则取:二维数组x = 数学x + 2500,二维数组y = 4500 - 数学y,转化后便开始遍历。该算法的 Java 代码实现如下:
public class Main{
//矩阵规模较上面分析的偏大一点确保下标不越界,用以记录该点是否为黑色,即该点是否遍历过
public static boolean[][] record = new boolean[10000][10000];
//记录黑色点个数
public static int count;
//树结点
public static class Node {
int x, y, dis;//x 与 y 为坐标,dis 表示该点到源点的距离
public Node() {}
public Node(int x, int y, int dis) {
this.x = x;
this.y = y;
this.dis = dis;
}
}
public static void main(String[] args) {
// int[][] source = {
{0,0},{2020,11},{11,14},{2000,2000}};//数学二维坐标轴下的坐标
int[][] dir = {
{-1,0},{0,1},{1,0},{0,-1}};//模拟方向的数组
count = 4;//将个数初始化为4
Queue<Node> query = new LinkedList<Node>();//创建队列用以存储当前结点
/**
* 将源点加入到队列中
*/
query.add(new Node(2500, 4500, 0));
query.add(new Node(4520, 4489, 0));
query.add(new Node(2511, 4486, 0));
query.add(new Node(4500, 2500, 0));
/**
* 初始化访问数组
*/
record[4019][2019] = true;
record[4005][2030] = true;
record[4008][4039] = true;
record[2019][4019] = true;
//开始广度优先搜索遍历
while(!query.isEmpty()) {
Node node = query.poll();
for(int i = 0; i < 4; i++) {
//对当前队列头结点进行四个方向的扩散
Node next = new Node();
next.x = node.x + dir[i][0];
next.y = node.y + dir[i][1];
next.dis = node.dis + 1;//距离源点距离 + 1
//判断是否没有遍历过且距离源点距离小于或等于 2020
if(!record[next.x][next.y] && next.dis <= 2020) {
record[next.x][next.y] = true;//标记当前遍历的点已经访问过
count++;//计数器 + 1
query.add(next);//将该点加入队列
}
}
}
System.out.println(count);
}
}