# DFS# Graph Traversal# Array Manipulation

n700 - 蝸牛的踩地雷攻略 3 (點方塊)

🔗 前往 ZeroJudge 原題

題目描述

題目要求模擬踩地雷遊戲,給定地雷分佈和起始點,輸出點擊起始點後的地圖狀態。地圖上 # 表示未翻開的格子,* 表示地雷,數字表示周圍地雷數量,_ 表示該格子及其周圍均無地雷。

解題思路

本題的核心是使用深度優先搜尋 (DFS) 演算法來模擬點擊空格後的連鎖反應。首先,計算每個格子周圍的地雷數量,並儲存在 ct 陣列中。然後,從起始點開始進行 DFS,如果當前格子沒有地雷,且周圍也沒有地雷,則將其標記為已翻開 (open 陣列),並遞迴地翻開其周圍的格子。如果當前格子有地雷,則停止 DFS。最後,根據 openct 陣列的狀態,輸出地圖。

複雜度分析

  • 時間複雜度: O(n*m),其中 n 是地圖的高度,m 是地圖的寬度。因為 DFS 最多會遍歷所有格子一次。
  • 空間複雜度: O(nm),主要用於儲存 ctopen 陣列,以及 DFS 的遞迴堆疊空間。在最壞情況下,遞迴深度可能達到 nm。

程式碼

#include <iostream>
using namespace std;
int ct[31][31];
bool open[31][31];
void dfs(int x,int y,int n,int m){
    if(x<0 || x>=n || y<0 || y>=m || open[x][y]){
        return;
    }
    open[x][y]=true;
    if(ct[x][y]>0){
        return;
    }
    for(int i=-1;i<=1;i++){
        for(int j=-1;j<=1;j++){
            dfs(x+i,y+j,n,m);
        }
    }
}
int main(){
    int n,m,x,y;
    cin >> n >> m >> x >> y;
    string s[n];
    for(int i=0;i<n;i++){
        cin >> s[i];
        for(int j=0;j<m;j++){
            if(s[i][j]=='*'){
                for(int ii=-1;ii<=1;ii++){
                    for(int jj=-1;jj<=1;jj++){
                        if(i+ii>=0 && i+ii<n && j+jj>=0 && j+jj<m){
                            ct[i+ii][j+jj]++;
                        }
                    }
                }
            }
        }
    }
    --x;--y;
    dfs(x,y,n,m);
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(open[i][j]){
                if(ct[i][j]){
                    cout << ct[i][j];
                }
                else{
                    cout << "_";
                }
            }else {
                cout << "#";
            }
        }
        cout << '\n';
    }
}

Discussion