公式

B - Crop 解説 by harurun4635


問題文にかかれている操作を愚直に実装しても良いでしょう。しかし、実装を楽にする工夫がいくつかあるので紹介します。


実装 1

  • 「すべての黒いピクセルが含まれるような最小の長方形」を考えて、その範囲のみを出力する

と考えるとよいかもしれません。これは以下のように実装できます。


実装例(Python)

H, W = map(int, input().split())
C = [input() for _ in range(H)]

u, d = H, -1
l, r = W, -1

for i in range(H):
    for j in range(W):
        if C[i][j] == "#":
            u, d = min(u, i), max(d, i)
            l, r = min(l, j), max(r, j)

for i in range(u, d + 1):
    print(C[i][l:r + 1])

実装例(C++)

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

int main() {
    int H, W;
    cin >> H >> W;

    vector<string> C(H);
    for (int i = 0; i < H; i++) cin >> C[i];

    int u = H, d = -1;
    int l = W, r = -1;

    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {
        if (C[i][j] == '#') {
            u = min(u, i); d = max(d, i);
            l = min(l, j); r = max(r, j);
        }
    }

    for (int i = u; i <= d; i++) {
        for (int j = l; j <= r; j++) {
            cout << C[i][j];
        }
        cout << endl;
    }

    return 0;
}

実装 2

具体的に操作を実装しますが、削除する行・列が変わるのが厄介です。そのため、削除する順番は自由であることを利用して

  • 「グリッドを \(90^{\circ} \) 回転させ、消せなくなるまで一番上の行を削除する」を \(4\) 回繰り返す

と考えてもよいかもしれません。

「グリッドの回転」はたまに用いられるので、関数として用意している方も少なくないかもしれません。


実装例(Python)

def rotate(a): return ["".join(r) for r in zip(*a[::-1])]
    
H, W = map(int, input().split())
C = [input() for _ in range(H)]

for _ in range(4):
    while not "#" in C[0]:
        C = C[1:]
    C = rotate(C)

print(*C, sep = "\n")

実装例(C++)

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

vector<string> rotate(vector<string> a) {
    int h = a.size(), w = a[0].size();
    vector<string> res(w, string(h, '.'));
    for (int i = 0; i < h; i++) for (int j = 0; j < w; j++) {
        res[j][h - 1 - i] = a[i][j];
    }
    return res;
}

int main() {
    int H, W;
    cin >> H >> W;

    vector<string> C(H);
    for (int i = 0; i < H; i++) cin >> C[i];

    for (int t = 0; t < 4; t++) {
        while (true) {
            int ok = 1;
            for (int j = 0; j < C[0].size(); j++) ok &= C[0][j] == '.';
            if (!ok) break;
            C.erase(begin(C));
        }
        C = rotate(C);
    }
    
    for(auto c : C) cout << c << endl;
    return 0;
}

投稿日時:
最終更新: