頭良くなりたい人

文系大学生shadeのブログです。競技プログラミングや人文学の話題,受験ネタなど。

ABC075 B - Minesweeper

問題はこちら atcoder.jp

方針

基本的な動作は,「各マスについて,周囲8マスの爆弾の数を数える」ということですが,端のマスには調べるべき8マスが存在しないので,それをどう処理するかが一つのポイントだろうと思います。

私は,マス目の周囲にダミーの要素Nを入れる,という方法を取っています。

下のコードでは肝心の爆弾の数を数える処理が冗長になってしまっていますが,解説PDF にうまい手法が紹介されています。

コード

#include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0; i<(n); i++)
 
int main(){
    int h,w;
    cin>>h>>w;
 
    vector<string> s(h+2);
    REP(i,h+2){
        if(i==0|| i==h+1){
            REP(j,w+2){
                s[i]+="N";
            }
        }else{
            cin>>s[i];
            s[i].insert(0,"N");
            s[i].insert(w+1,"N");
        }
    }
 
    for(int i=1; i<h+1; i++){
        for(int j=1; j<w+1; j++){
            if(s[i][j]=='#'){
                continue;
            }
            int count=0;
            // 上の列
            REP(k,3){
                if(s[i-1][j+k-1]=='#'){
                    count++;
                }
            }
            // 下の列
            REP(k,3){
                if(s[i+1][j+k-1]=='#'){
                    count++;
                }
            }
            // 左右
            if(s[i][j-1]=='#'){
                count++;
            }
            if(s[i][j+1]=='#'){
                count++;
            }
 
            s[i][j]=count+'0'; // 数値を文字に変換
        }
    }
 
    for(int i=1; i<h+1; i++){
        for(int j=1; j<w+1; j++){
            cout<<s[i][j];
            if(j==w){
                cout<<endl;
            }
        }
    }  
}