はまやんはまやんはまやん

hamayanhamayan's blog

76本のトロンボーン [yukicoder No.640]

https://yukicoder.me/problems/no/640

解法

https://yukicoder.me/submissions/246059

長さN-1なので、例えば縦に一本置くと大分横に置きづらくなる。
横を上端に1つに置くと、縦に置くには下にそろえて置くしか無い。
端以外に置くと縦は置けなくなる。
これを考えると、置き方はそんなになさそうな感じがある。
 
なので、
「上端に右寄せで横を置いて、他は全部縦(最も左の縦は上も使える)」
「上端に左寄せで横を置いて、他は全部縦(最も右の縦は上も使える)」
「全部縦」
を全部試すが、下に置くとか全部横とかは盤面を回転させて4方向チェックすることで試せる。
 
これ以外にも

AAAB
C  B
C  B
CDDD

というのもある。
これもちょっとずらしたやつがあるが、左右対称移動させて、判定し直せば判定は1つ書くだけでいい。

int N;
vector<vector<char>> S;
string SS[101];
//---------------------------------------------------------------------------------------------------
template<typename T> vector<vector<T>> rotateClockwise(vector<vector<T>> g) {
    int n = g.size();
    int m = g[0].size();
    vector<vector<T>> res(m, vector<T>(n));
    rep(i, 0, n) rep(j, 0, m) res[j][n - i - 1] = g[i][j];
    return res;
}
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> N;
    rep(y, 0, N) cin >> SS[y];
    S.resize(N, vector<char>(N));
    rep(y, 0, N) rep(x, 0, N) S[y][x] = SS[y][x];
    int ans = 0;

    rep(i, 0, 4) {

        // 1 : 全部縦
        {
            int cnt = 0;
            rep(x, 0, N) {
                int ok = 0;
                int c = 0;
                rep(y, 0, N - 1) if (S[y][x] == '.') c++;
                if (c == N - 1) ok = 1;
                c = 0;
                rep(y, 1, N) if (S[y][x] == '.') c++;
                if (c == N - 1) ok = 1;
                if (ok) cnt++;
            }
            chmax(ans, cnt);
        }

        // 2-1 : 縦+上右寄せ
        {
            int cnt = 0, ok, c;
            
            c = 0;
            rep(x, 1, N) if (S[0][x] == '.') c++;
            if (c == N - 1) cnt++;

            rep(x, 1, N) {
                int c = 0;
                rep(y, 1, N) if (S[y][x] == '.') c++;
                if (c == N - 1) cnt++;
            }

            ok = 0;
            c = 0;
            rep(y, 0, N - 1) if (S[y][0] == '.') c++;
            if (c == N - 1) ok = 1;
            c = 0;
            rep(y, 1, N) if (S[y][0] == '.') c++;
            if (c == N - 1) ok = 1;
            if (ok) cnt++;
            chmax(ans, cnt);
        }

        // 2-2 : 縦+上左寄せ
        {
            int cnt = 0, ok, c;

            c = 0;
            rep(x, 0, N - 1) if (S[0][x] == '.') c++;
            if (c == N - 1) cnt++;

            rep(x, 0, N - 1) {
                int c = 0;
                rep(y, 1, N) if (S[y][x] == '.') c++;
                if (c == N - 1) cnt++;
            }

            ok = 0;
            c = 0;
            rep(y, 0, N - 1) if (S[y][N-1] == '.') c++;
            if (c == N - 1) ok = 1;
            c = 0;
            rep(y, 1, N) if (S[y][N-1] == '.') c++;
            if (c == N - 1) ok = 1;
            if (ok) cnt++;
            chmax(ans, cnt);
        }

        S = rotateClockwise(S);

    }

    // 特殊パターン
    {
        int cnt = 0, c;

        c = 0;
        rep(y, 0, N - 1) if (S[y][0] == '.') c++;
        if (c == N - 1) cnt++;
        c = 0;
        rep(x, 0, N - 1) if (S[N - 1][x] == '.') c++;
        if (c == N - 1) cnt++;
        c = 0;
        rep(y, 1, N) if (S[y][N - 1] == '.') c++;
        if (c == N - 1) cnt++;
        c = 0;
        rep(x, 1, N) if (S[0][x] == '.') c++;
        if (c == N - 1) cnt++;

        chmax(ans, cnt);
    }

    rep(y, 0, N) rep(x, 0, N / 2) swap(S[y][x], S[y][N - 1 - x]);

    {
        int cnt = 0, c;

        c = 0;
        rep(y, 0, N - 1) if (S[y][0] == '.') c++;
        if (c == N - 1) cnt++;
        c = 0;
        rep(x, 0, N - 1) if (S[N - 1][x] == '.') c++;
        if (c == N - 1) cnt++;
        c = 0;
        rep(y, 1, N) if (S[y][N - 1] == '.') c++;
        if (c == N - 1) cnt++;
        c = 0;
        rep(x, 1, N) if (S[0][x] == '.') c++;
        if (c == N - 1) cnt++;

        chmax(ans, cnt);
    }

    cout << ans << endl;
}