首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

HDU 5254 暴力模擬:網格擴散過程模擬求最終黑格數

     編輯:關於C++

題目大意

n×m 網格,初始 k 個黑格 (1),其餘白格 (0)。反覆執行:若某白格的上下左右四個方向中,存在「垂直方向有黑格」且「水平方向有黑格」 (即四個角落方向各有一黑),則該白格變黑。直到無新黑格產生。求最終黑格總數。

直接模擬法 (O(n·m·迴圈數))

資料範圍:n,m ≤ 500,k ≤ n·m。最壞全白格需 O(n+m) 輪才穩定,總複雜度 O((n·m)·(n+m)) ≈ 1.25×10⁸,配合簡單陣列操作在 C++ 1s 內通常能過。

優化關鍵點

  1. 雙緩衝陣列:cur 存當前狀態,nxt 存下一輪狀態,避免同輪內新黑格影響判斷。
  2. 只掃描白格:黑格永不變白,僅檢查 cur[i][j]==0 的格子。
  3. 提前終止:某輪無新增黑格即跳出。
  4. 判斷條件簡化:四個角落 (i±1, j±1) 中任一對角同時存在垂直/水平黑格即可。等價於:(up && left) || (up && right) || (down && left) || (down && right)。

完整優化程式碼 (C++)

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

const int MAXN = 505;
int n, m, k;
bool cur[MAXN][MAXN], nxt[MAXN][MAXN];

inline bool canTurn(int x, int y) {
    if (x <= 0 || x >= n-1 || y <= 0 || y >= m-1) return false; // 邊界無法滿足四方向
    return (cur[x-1][y] && cur[x][y-1]) ||
           (cur[x-1][y] && cur[x][y+1]) ||
           (cur[x+1][y] && cur[x][y-1]) ||
           (cur[x+1][y] && cur[x][y+1]);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T; cin >> T;
    for (int cas = 1; cas <= T; ++cas) {
        cin >> n >> m >> k;
        memset(cur, 0, sizeof(cur));
        int initBlack = 0;
        for (int i = 0, x, y; i < k; ++i) {
            cin >> x >> y;
            --x; --y; // 0-based
            if (!cur[x][y]) { cur[x][y] = true; ++initBlack; }
        }

        int added = 0;
        while (true) {
            memcpy(nxt, cur, sizeof(cur));
            int cnt = 0;
            for (int i = 1; i < n-1; ++i)
                for (int j = 1; j < m-1; ++j)
                    if (!cur[i][j] && canTurn(i, j)) {
                        nxt[i][j] = true;
                        ++cnt;
                    }
            if (cnt == 0) break;
            added += cnt;
            memcpy(cur, nxt, sizeof(cur));
        }
        cout << "Case #" << cas << ":\n" << initBlack + added << "\n";
    }
    return 0;
}

複雜度分析

  • 每輪掃描 O(n·m),最多 O(max(n,m)) 輪。
  • 實測 500×500 全白格約 500 輪,約 1.25 億次簡單布林操作,C++ O2 約 0.3~0.5s。
  • 記憶體:兩個 505×505 bool 陣列 < 0.5 MB。

進一步優化思路 (BFS/多源擴散)

觀察規則:黑格像「感染源」向四角擴散。可建立「可被感染」的白格隊列,僅處理受影響區域,類似多源 BFS,可降至 O(n·m) 總複雜度。但本題暴力已足夠,除非時限極嚴。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved