洛谷-P1789-插火把

## 题目描述

话说有一天 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;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值