魔王迷宮

解題想法

1. 設立二維陣列

題目敘述中提到, n,m,kn, m, k 可以用來代表一個大小為 n×mn \times m 的二維陣列,和五個長度為 kk 的一維陣列。因此,我們可以建立這些陣列來記錄:

  1. bool bomb[n][m] : 記錄 (n,m)(n, m) 是否有炸彈。
  2. bool explode[n][m] : 記錄 (n,m)(n, m) 是否爆炸。
  3. int r[k], c[k] : 第 kk 位魔王的起始位置 (r,c)(r, c)
  4. int s[k], t[k] : 第 kk 位魔王每回合垂直移動 ss,平行移動 tt

以上六個陣列將會在解題過程中持續使用。

2. 魔王放置炸彈

每回合一開始時,每位魔王都要在自己位置上放炸彈,即 r[]c[] 。因此我們可以將狀態存入 bomb[][] 中,代表此地有炸彈:

for (int i = 0; i < k; i++) {
    bomb[r[i]][c[i]]++;
}

3. 魔王移動

魔王放完炸彈後,每位魔王會依自己的移動方式移動。因此我們可以將其原位置 r[]c[] ,各自加上 s[]t[] ,從而更新其位置:

for (int i = 0; i < k; i++) {
    bomb[r[i]][c[i]]++;
    r[i] += s[i];
    c[i] += t[i];
}

4. 魔王刪除

題目敘述中,有給予兩個魔王死亡的條件:

  1. 魔王出界。
  2. 魔王碰到炸彈並炸死。

因此,我們可以做出以下兩個判斷式。

1. 出界檢測

當魔王位置超出 [0,n)[0, n)[0,m)[0, m) 時,以下判斷式可以將魔王移出:

for (int i = 0; i < k; i++) {
	if (r[i] < 0 || r[i] >= n || c[i] < 0 || c[i] >= m) {
	    r[i] = c[i] = -100;
	    lef--; //魔王剩餘數量
	}
	...
}

2. 炸彈檢測

當魔王碰到炸彈時,以下判斷式可以將此位置的 explode[] 設為 true ,之後來到這位置魔王都會被移出,同時將此位置的 bomb[] 設定為 false

for (int i = 0; i < k; i++) {
	...
	if (bomb[i]) {
	    r[i] = c[i] = -100;
	    lef--; //魔王剩餘數量
	}
}

5. 清除炸彈

每次回合結束後,會將 explode[] 的所有值設定為 false ,避免影響到之後的回合:

memset(explode, 0, sizeof(explode));

範例程式

#include <bits/stdc++.h>
using namespace std;

int n, m, k, lef = 0, r[505], c[505], s[505], t[505], bomb[105][105], ans = 0;
bool explode[105][105];

int main() {
    memset(bomb, 0, sizeof(bomb));
    memset(explode, 0, sizeof(explode));
    cin >> n >> m >> k;
    for (int i = 0; i < k; i++) cin >> r[i] >> c[i] >> s[i] >> t[i];
    lef = k;
    do {
        for (int i = 0; i < k; i++) {
            if (r[i] == -100 && c[i] == -100) continue;
            bomb[r[i]][c[i]]++;
            r[i] += s[i];
            c[i] += t[i];
        }
        for (int i = 0; i < k; i++) {
            if (r[i] == -100 && c[i] == -100) continue;
            if (r[i] < 0 || r[i] >= n || c[i] < 0 || c[i] >= m) {
                r[i] = c[i] = -100;
                lef--;
            }
            else if (bomb[r[i]][c[i]] || explode[r[i]][c[i]]) {
                bomb[r[i]][c[i]] = 0, explode[r[i]][c[i]] = 1;
                r[i] = c[i] = -100;
                lef--;
            }
        }
        memset(explode, 0, sizeof(explode));
    } while (lef);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (bomb[i][j]) ans++;
        }
    }
    cout << ans << '\n';
    return 0;
}