## 题目描述
话说有一天 linyorson 在“我的世界”开了一个 $n \times n$ 的方阵,现在他有 $m$ 个火把和 $k$ 个萤石,分别放在 $(x_1, y_1) \sim (x_m, y_m)$ 和 $(o_1, p_1) \sim (o_k, p_k)$ 的位置,没有光并且没放东西的地方会生成怪物。请问在这个方阵中有几个点会生成怪物?
火把照亮的范围是:
|暗|暗| 光 |暗|暗| |暗|光| 光 |光|暗| |光|光|火把|光|光| |暗|光| 光 |光|暗| |暗|暗| 光 |暗|暗|
萤石照亮的范围:
|光|光| 光 |光|光| |光|光| 光 |光|光| |光|光|萤石|光|光| |光|光| 光 |光|光| |光|光| 光 |光|光|
输入格式
输入共 m+k+1 行。
第一行为n,m,k。
第 2 到第m+1 行分别是火把的位置 Xi,Yi。
第 m+2到第 m+k+1行分别是萤石的位置Oi,Pi。注:可能没有萤石,但一定有火把。
输出格式
有几个点会生出怪物。
输入输出样例
输入 #1
5 1 0 3 3
输出 #1
12
本题破题点在于模拟创建火把和萤石照亮范围的矩阵,由于二者照亮范围相对一致所以可以直接合并一同照亮;第二,照亮的格子直接用++来表示非0即可(全局变量定义的数组默认初始化为0);
来到第三点,也就是如何去让数组更高效简洁的“照亮范围”,下文代码中有abs(i) + abs(j) <= 2 ,完美的控制了火把的点亮范围(坐标之和不大于2),也就是十字形;至于萤石,5*5的矩阵全部点亮就好了。最后,判断数组是否越界也非常重要,具体看代码check部分。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int a[105][105];
int n;
bool check(int x,int y)//判断是否越界的函数,因为下面会用到判断数组是否越界
{
if(x<1||y<1||x>n||y>n) return false ;
return true;
}
int main ()
{
for (int i = 1 ; i<= n; i++)
{
for(int j = 1 ; j <= n ; j++)
{
cin >> a[i][j];
}
}
int m,k;
cin >> n >> m >> k;
int sum = m + k,cnt = 1;
while(sum--)
{
int x , y ;
cin >> x >> y;
for(int i = - 2 ; i <=2 ; i++)
{
for(int j = -2 ; j<=2 ; j++)//构建5*5的矩阵
{
//cnt > m 也就意味着到了萤石的环节;
//||的另一边也就是火把的情况;
if((cnt>m||abs(i) + abs(j) <= 2)&&check(i+x,y+j))
{
a[x+i][y+j]++;
}
}
}
cnt++;//这里用一个小小的计数器来判断是否到了萤石的环节
//用for循环也可以且更方便
}
int ans = 0;//统计未照亮的部分
for(int i = 1; i<= n ; i++)
{
for(int j = 1 ; j<=n ; j++)
{
if(a[i][j]==0) ans++;
}
}
printf("%d",ans);
return 0;
}