🕒 2020/05/02
🔄 2024/10/14
第二回 アルゴリズム実技検定 C - ⼭崩し 解説
🧙
問題
問題文は本家サイトにあります:第二回 アルゴリズム実技検定 C - ⼭崩し
問題概要
縦 $N$ マス、横 $2N-1$ マスのマス目があります。上から $i$ 行目、左から $j$ 列目のマスは、 $|j-N|\lt i$ を満たしていたら黒、他は白に塗られています。以下は、 $N=3$ のときの例です。
..#.. .###. #####
'.' が白を、'#' が黒を表しています。ここで、黒いマスのうち、いくつかに 'X' を書いた状態が入力されます。これに対し、以下の操作をした結果を返しなさい。
操作: $i=N-1, N-2,\cdots,1$ の順番で、次の処理を行う。
処理: $2\leqq j \leqq 2N-2$ に対して、マス $(i,j)$ が黒いマスで 'X' が書かれておらず、マス $(i+1,j-1)$, $(i+1,j)$, $(i+1,j+1)$ のうち1つ以上に 'X' が書かれていれば、マス $(i,j)$ に 'X' を書く。
制約
$2\leqq N \leqq 50$
解説
言われた通りの処理を行っていきます。
まずは、状態を配列に格納していきます。1行ずつ格納していきましょう。
次に、下から2行目に対して、黒いマスを見ていきます。マスが '#' の状態で、左下、下、右下のどれかが 'X' かどうかを確認していきます。これを上に向かって続けていけばOKです。C++では、次のように書けます。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N; cin >> N;
vector<string> S(N);
for (int i = 0; i < N; i++) {
cin >> S[i];
}
for (int i = N - 2; i >= 0; i--) {
for (int j = 1; j < 2 * N - 2; j++) {
if (S[i][j] != '#') continue;
if (S[i + 1][j - 1] == 'X' || S[i + 1][j] == 'X' || S[i + 1][j + 1] == 'X') {
S[i][j] = 'X';
}
}
}
for (int i = 0; i < N; i++) {
cout << S[i] << '\\n';
}
return 0;
}