题解 P1789 【Mc生存】插火把

· · 题解

由于本题解之前的版本存在一定纰漏,故进行整改。

观察到这是一道很简单的模拟题,那么我们可以思考一下怎样才能写出更加简短的代码。

对于火把的照亮范围:

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

我们可分为两部分处理:中间的 3\times3 区域和上下左右的四个位置。

对于萤石就更简单了,只需将其周围 5\times5 大小的格子标记即可。

注意标记之前先判断坐标是否越界,否则可能出现运行错误。

#include <iostream>
using namespace std;
const int N = 105;

int n, m, k;
bool a[N][N]; // a[x][y] 表示坐标为 (x, y) 的点是否被照亮


bool in(int x, int y) { // 坐标为 (x, y) 的点是否在规定的界内
    return (x >= 1 && x <= n && y >= 1 && y <= n);
}

int main() {
    int x, y, ans = 0;
    cin >> n >> m >> k;
    for(int i = 1; i <= m; ++i) {
        cin >> x >> y;
        for(int x0 = x - 1; x0 <= x + 1; ++x0)
            for(int y0 = y - 1; y0 <= y + 1; ++y0)
                if(in(x0, y0) == true) a[x0][y0] = true;
        if(in(x - 2, y) == true) a[x - 2][y] = true;
        if(in(x + 2, y) == true) a[x + 2][y] = true;
        if(in(x, y - 2) == true) a[x][y - 2] = true;
        if(in(x, y + 2) == true) a[x][y + 2] = true;
    }
    for(int i = 1; i <= k; ++i) {
        cin >> x >> y;
        for(int x0 = x - 2; x0 <= x + 2; ++x0)
            for(int y0 = y - 2; y0 <= y + 2; ++y0)
                if(in(x0, y0) == true) a[x0][y0] = true;
    }
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            if(a[i][j] == false) ++ans;
    cout << ans << '\n';
    return 0;
}