#2021年 第12届 蓝桥杯 第2次模拟赛真题 九I【Java版】
九、I
问题描述
小蓝负责花园的灌溉工作。
花园可以看成一个 n 行 m 列的方格图形。中间有一部分位置上安装有出水管。
小蓝可以控制一个按钮同时打开所有的出水管,打开时,有出水管的位置可以被认为已经灌溉好。
每经过一分钟,水就会向四面扩展一个方格,被扩展到的方格可以被认为已经灌溉好。即如果前一分钟某一个方格被灌溉好,则下一分钟它上下左右的四个方格也被灌溉好。
给定花园水管的位置,请问 k 分钟后,有多少个方格被灌溉好?
输入格式
输入的第一行包含两个整数 n, m。
第二行包含一个整数 t,表示出水管的数量。
接下来 t 行描述出水管的位置,其中第 i 行包含两个数 r, c 表示第 r 行第 c 列有一个排水管。
接下来一行包含一个整数 k。
输出格式
输出一个整数,表示答案。
样例输入
3 6
2
2 2
3 4
1
样例输出
9
样例说明
用1表示灌溉到,0表示未灌溉到。
打开水管时:
000000
010000
000100
1分钟后:
010000
111100
011110
共有9个方格被灌溉好。
数据规模和约定
对于所有评测用例,1 <= n, m <= 100, 1 <= t <= 10, 1 <= k <= 100。
思路:
先将最开始的t个水管在a,b中的位置置为1,然后将f函数,进行K次,f函数的作用就是,遍历a里面有水的地方(就叫做x位置),再在b里面x位置的上下左右都变成有水(置为1),然后时间K就经过1;再将b现在的状态赋值给a,这样就做完一次
为什么要用两个数组:比如只有0,0位置有水管,时间k为1,一秒过后(0,1)(1,0)位置变得有水,答案为3。因为如果在一个数组里做标记,循环继续看到(0,1)有水,会继续把(0,1)的上下左右标记这样最后的答案就变成17
static int sum=0;//计数
static int[][] a;
static int[][] b;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();//行
int m=sc.nextInt();//列
//两个数组
//a是上一秒有水方格的记录
//b是根据a(也就是上一秒)哪些地方有水,来标记这一秒哪些地方有水
a=new int[n][m];
b=new int [n][m];
int t=sc.nextInt();//水管数
int r,c;//行、列
for (int i = 0; i <t; i++) {
r=sc.nextInt()-1;
c=sc.nextInt()-1;
a[r][c]=1;
b[r][c]=1;
}
int k=sc.nextInt();//时间
for (int i = 0; i <k; i++) {
f(0,0);//调用函数
a=b;//将这一秒水蔓延后的效果,赋给a
}
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++){
if(a[i][j]==1) {
sum++;
}
}
}
System.out.println(sum);
}
private static void f(int i, int j) {
if(i==a.length-1&&j==a[0].length-1)return;
if(a[i][j]==1) {
if(i-1>=0) {
b[i-1][j]=1;}
if(j-1>=0) {
b[i][j-1]=1;}
if(j+1<=a[0].length-1) {
b[i][j+1]=1;}
if(i+1<=a.length-1) {
b[i+1][j]=1;}
}
f(i+(j+1)/a[0].length, (j+1)%a[0].length);
}