置頂

我的 VPython 教學文件 (HackMD 版本)

VPython 教學文件目錄 安裝及測試 基本語法 等速度直線運動 自由落下 終端速度 水平抛射 使用For迴圈計算水平抛射資料 斜向抛射 圓周運動 簡諧運動 單擺 木塊彈簧系統分離 重力及簡諧 行星運動 相疊木塊 雙重簡諧運動 一維彈性碰撞 ...

熱門文章

2026年11月14日 星期六

ZeroJudge 解題筆記:c231.踩地雷

作者:王一哲
日期:2026年11月14日


ZeroJudge 題目連結:c231.踩地雷

解題想法


每組測資第一列為 3 個整數 $a, b, n$,$a, b$ 代表地圖大小為 $a \times b$,$n$ 代表有地雷數量。接下來 $n$ 列每列有 2 個整數 $row_i, col_i ~(1 \leq row_i, col_i \leq 10^4)$,代表第 $i$ 個地雷的位置。每個地雷周圍 8 格有感測器,如果某一個地雷爆炸時,周圍 8 格之中有其它地雷的感測器,則這些地雷會跟著被引爆。如果要用誘導彈引爆所有的地雷,至少需要幾個誘導彈?

這題我用 BFS 處理。先將地雷的坐標存入串列 $mines$,將感測器坐標對應的地雷編號存入字典 $sensors$,key 值為 tuple 格式的坐標 $(r, c)$,value 為串列格式。另外用一個 set 或陣列 $rem$ 記錄目前未被引爆的地雷編號。用一個 for 迴圈依序讀取地雷編號,如果遇到還沒有被引爆的地雷,答案 $ans + 1$,將這個地雷編號加入待走訪佇列 $que$,用 BFS 跑完所有會連鎖反應的地雷。這個寫法有點慢,但是比較容易理解。

Python 程式碼


使用時間約為 0.2 s,記憶體約為 42 MB,通過測試。
def solve():
    import sys
    from collections import deque

    result = []
    data = sys.stdin.read().split()
    ptr = 0
    while ptr < len(data):
        a = int(data[ptr])  # 地圖 a 列
        b = int(data[ptr + 1])  # b 欄
        n = int(data[ptr + 2])  # n 個地雷
        ptr += 3

        mines = []  # 地雷坐標
        sensors = dict()  # 感測器坐標對應的地雷編號 (r, c): idx
        dr = (0, 1, 1, 1, 0, -1, -1, -1)  # 周圍 8 格的位移量
        dc = (1, 1, 0, -1, -1, -1, 0, 1)  # 周圍 8 格的位移量
        for i in range(n):
            r = int(data[ptr])
            c = int(data[ptr + 1])
            ptr += 2
            mines.append((r, c))
            for j in range(8):
                nr, nc = r + dr[j], c + dc[j]
                if (nr, nc) not in sensors:
                    sensors[nr, nc] = [i]
                else:
                    sensors[nr, nc].append(i)
        
        ans = 0  # 答案
        rem = set(range(n))  # 剩下的地雷
        for i in range(n):
            if i in rem:
                rem.remove(i)
                ans += 1
                # 測試周圍 8 格是否有其它未爆地雷的感測器
                que = deque([i])
                while que:
                    r, c = mines[que.popleft()]
                    for j in range(8):
                        nr, nc = r + dr[j], c + dc[j]
                        for k in sensors[nr, nc]:
                            if k in rem:
                                rem.remove(k)
                                que.append(k)
        result.append(f"{ans:d}\n")
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()


C++ 程式碼


使用時間約為 77 ms,記憶體約為 15.8 MB,通過測試。
#include <iostream>
#include <vector>
#include <utility>
#include <map>
#include <queue>
using namespace std;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int a, b, n;  // 地圖 a 列、b 欄,n 個地雷
    while(cin >> a >> b >> n) {
        vector<pair<int, int>> mines (n);  // 地雷坐標
        map<pair<int, int>, vector<int>> sensors;  // 感測器坐標對應的地雷編號 (r, c): idx
        int dr[8] = {0, 1, 1, 1, 0, -1, -1, -1};  // 周圍 8 格的位移量
        int dc[8] = {1, 1, 0, -1, -1, -1, 0, 1};  // 周圍 8 格的位移量
        for(int i = 0; i < n; i++) {
            int r, c;
            cin >> r >> c;
            mines[i] = make_pair(r, c);
            for(int j = 0; j < 8; j++) {
                int nr = r + dr[j], nc = c + dc[j];
                pair<int, int> pos = {nr, nc};
                sensors[pos].push_back(i);
            }
        }

        int ans = 0;  // 答案
        vector<bool> rem (n, true);  // 剩下的地雷
        for(int i = 0; i < n; i++) {
            if (rem[i]) {
                rem[i] = false;
                ans++;
                // 測試周圍 8 格是否有其它未爆地雷的感測器
                queue<int> que;
                que.push(i);
                while(!que.empty()) {
                    auto mine = mines[que.front()];
                    que.pop();
                    for(int j = 0; j < 8; j++) {
                        pair<int, int> nxt = {mine.first + dr[j], mine.second + dc[j]};
                        for(int k : sensors[nxt]) {
                            if (rem[k]) {
                                rem[k] = false;
                                que.push(k);
                            }
                        }
                    }
                }
            }
        }

        cout << ans << "\n";
    }
    return 0;
}


沒有留言:

張貼留言