快轉到主要內容

魔王迷宮

目錄

解題想法
#

1. 設立二維陣列
#

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

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

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

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, 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;
}
Piau 的筆記本
作者
Piau 的筆記本
希望我寫下來的東西能夠長久的記在我的腦中