けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder ABC 366 B - Vertical Writing (5Q, 灰色, 200 点)

問題文がやたら難読すぎる!!!

問題概要(意訳)

 N 個の文字列  S_{1}, S_{2}, \dots, S_{N} が与えられる。これに対して、次のように縦横をひっくり返して、隙間を文字 * で埋めたようなものを出力せよ。

before

red
orang
blue
yellow
green
gray
skyblue
black

after

bsggybor
lkrrelre
ayaeluad
cbyelen
kl*no*g
*u**w
*e

制約

  •  1 \le N \le 100
  •  1 \le |S_{i}| \le 100

考えたこと

もとの問題文はあまりにも難しいので、こういうときは先にサンプルを読むのも手だと思う。サンプルを見ると、やりたいことは比較的単純だとわかる。

さて、実装方法はいろいろあろうが、ここでは次のように考えた。


  •  M = \max(|S_{1}, S_{2}, \dots, S_{N}) とする
  •  M \times N のグリッドを用意する
  • グリッドのうち、文字列  S_{1}, S_{2}, \dots, S_{N} に対応する部分は埋めてしまう
  • グリッドの各行について、末尾の連続する * を削除する

コード

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

int main() {
    int N, M = 0;
    cin >> N;
    vector<string> S(N);
    for (int i = 0; i < N; i++) {
        cin >> S[i];
        M = max(M, (int)S[i].size());
    }

    vector<string> res(M, string(N, '*'));
    for (int i = 0; i < N; i++) for (int j = 0; j < S[N-i-1].size(); j++) {
        res[j][i] = S[N-i-1][j];
    }
    for (int i = 0; i < M; i++) {
        while (res[i].back() == '*') res[i].pop_back();
        cout << res[i] << endl;
    }
}