洛谷P1789“【MC生存】插火把”题解

题目

题目描述

话说有一天 linyorson 在“我的世界”开了一个 n×n 的方阵,现在他有 m 个火把和 k 个萤石,分别放在 (x1​,y1​)∼(xm​,ym​) 和(o1​,p1​)∼(ok​,pk​) 的位置,没有光并且没放东西的地方会生成怪物。请问在这个方阵中有几个点会生成怪物?

P.S. 火把的照亮范围是:

    |暗|暗| 光 |暗|暗|
    |暗|光| 光 |光|暗|
    |光|光|火把|光|光|
    |暗|光| 光 |光|暗|
    |暗|暗| 光 |暗|暗|

萤石:

    |光|光| 光 |光|光|
    |光|光| 光 |光|光|
    |光|光|萤石|光|光|
    |光|光| 光 |光|光|
    |光|光| 光 |光|光|

输入格式

输入共 m+k+1 行。
第一行为 n,m,k。
第 22 到第m+1 行分别是火把的位置 xi​,yi​。
第m+2 到第m+k+1 行分别是萤石的位置oi​,pi​。

注:可能没有萤石,但一定有火把。

输出格式

有几个点会生出怪物。

输入输出样例

输入 #1

5 1 0
3 3

输出 #1

12

说明/提示

数据保证,1≤n≤100,1≤m+k≤25,1≤m≤25,0≤k≤5。

题目网址

传送门


题解

思路

这道题很明显,用一个二维数组mp作为地图,然后按照输入去更新地图,被照亮了变为1,否则变为0。最后统计0的个数就行了。

程序分段解释

#include<iostream>
#include<vector>
using namespace std;
typedef vector<vector<int>> map;

引用。vector就是数组。之所以用typedef是因为太懒了,懒得每次写vector<vector<int>>了 

vector<int> fluorite_x{-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2},
            fluorite_y{-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2};
vector<int> match_x{2,0,-2,0,1,1,1,0,0,0,-1,-1,-1},
            match_y{0,2,0,-2,0,1,-1,1,0,-1,0,1,-1};

这两个数组是判断被照亮位置的。fluorite是萤石,match是火把。里面的数据都以火把或萤石的所在地为基础

int main()
{

开始主程序 

    int n,m,k,a,b;
    cin >> n >> m >> k;
    map mp;
    vector<int>z;
    for (int i = 0; i < n; i++)
    {
        for (int ii = 0; ii < n; ii++)
        {
            z.push_back(0);
        }
        mp.push_back(z);
        z.clear();
    }

定义 + 输入。map的定义上面有。z这个数组只用于输入,其他没用。n、m、k都是题目中的,这里不做解释。a、b是后期输入萤石与火把时它们的x、y。之所以把mp里面塞满0 ...... 额,后面讲。

    for (int i = 0; i < m; i++)
    {
        cin >> a >> b;
        a--;
        b--;
        for (int ii = 0; ii < match_x.size(); ii++)
        {
            if(match_x[ii] + a <= n - 1 && match_y[ii] + b <= n - 1 && match_x[ii] + a >= 0 && match_y[ii] + b >= 0)
            {
                mp[match_x[ii] + a][match_y[ii] + b] = 1;
            }
        }
    }
    for (int i = 0; i < k; i++)
    {
        cin >> a >> b;
        a--;
        b--;
        for (int ii = 0; ii < fluorite_x.size(); ii++)
        {
            if(fluorite_x[ii] + a <= n - 1 && fluorite_y[ii] + b <= n - 1 && fluorite_x[ii] + a >= 0 && fluorite_y[ii] + b >= 0)
            {
                mp[fluorite_x[ii] + a][fluorite_y[ii] + b] = 1;
            }
        }
    }

(敲黑板) 

重点!!!!!

这里的两次循环分别是用来输入火把与萤石,并更改列表的。一开始a--、b--是因为刚刚输入进来的坐标起始点为1,而我们的起始点为0。现在解释一下为什么一开始全是0,现在变1。在这个列表里,0代表没有被照亮,1代表被照亮,也就是说,最后统计时,0代表会生成怪物,1代表不会。里面再来一层循环是为了遍历match_x/match_y、fluorite_x/fluorite_y。最后判断坐标点是否是照亮范围。

    int ans = 0;
    for(int i = 0;i < n;i++)
    {
        for(int ii = 0;ii < n;ii++)
        {
            if(!(mp[i][ii]))
            {
                ans++;
            }
        }
    }
    cout << ans << endl;

统计并输出。!(map[i][ii])等同于map[i][ii] == 0。

    return 0;
}

华丽的结束。

整程序 

#include<iostream>
#include<vector>
using namespace std;
typedef vector<vector<int>> map;
vector<int> fluorite_x{-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2},
            fluorite_y{-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2};
vector<int> match_x{2,0,-2,0,1,1,1,0,0,0,-1,-1,-1},
            match_y{0,2,0,-2,0,1,-1,1,0,-1,0,1,-1};
int main()
{
    int n,m,k,a,b;
    cin >> n >> m >> k;
    map mp;
    vector<int>z;
    for (int i = 0; i < n; i++)
    {
        for (int ii = 0; ii < n; ii++)
        {
            z.push_back(0);
        }
        mp.push_back(z);
        z.clear();
    }
    for (int i = 0; i < m; i++)
    {
        cin >> a >> b;
        a--;
        b--;
        for (int ii = 0; ii < match_x.size(); ii++)
        {
            if(match_x[ii] + a <= n - 1 && match_y[ii] + b <= n - 1 && match_x[ii] + a >= 0 && match_y[ii] + b >= 0)
            {
                mp[match_x[ii] + a][match_y[ii] + b] = 1;
            }
        }
    }
    for (int i = 0; i < k; i++)
    {
        cin >> a >> b;
        a--;
        b--;
        for (int ii = 0; ii < fluorite_x.size(); ii++)
        {
            if(fluorite_x[ii] + a <= n - 1 && fluorite_y[ii] + b <= n - 1 && fluorite_x[ii] + a >= 0 && fluorite_y[ii] + b >= 0)
            {
                mp[fluorite_x[ii] + a][fluorite_y[ii] + b] = 1;
            }
        }
    }
    int ans = 0;
    for(int i = 0;i < n;i++)
    {
        for(int ii = 0;ii < n;ii++)
        {
            if(!(mp[i][ii]))
            {
                ans++;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

最后......

感谢观看!

(求点个赞呗)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值