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

hamayanhamayan's blog

Palindromic Matrix [CODE FESTIVAL 2017 予選A C]

http://code-festival-2017-quala.contest.atcoder.jp/tasks/code_festival_2017_quala_c

解説

http://code-festival-2017-quala.contest.atcoder.jp/submissions/1617339

H,Wのパリティで場合分けする。

H,Wのどちらも偶数
この場合は、上下左右のブロックが全て同じになるため、同じパターンが4つできることになる。
そのため、全ての文字の個数が4の倍数であればYes

H,Wのどちらかが偶数
説明のため、Wが偶数であるとする。
この場合は、中心の行が横の回分でしか使われないため、ここは2の倍数でいい。
そのため、4で割ると2余る数がW/2個以下で、残りが4の倍数であればいい。
(以下というのは、足りない場合は4の倍数のやつを1つ崩して2つにしればいいため)

H,Wのどちらも奇数
この場合はど真ん中は4で割ると1余る数になる必要(1つ必要)がある。
あとは、4で割ると2余る数が使われるのが(H-1)/2+(W-1)/2以下であればいい。

int H, W;
string A[101];
#define NO "No"
#define YES "Yes"
//--------------------------------------------------------------------------------------------------
string solve() {
    map<char, int> cnt;
    rep(y, 0, H) rep(x, 0, W) cnt[A[y][x]]++;
 
    if (H % 2 == 0 && W % 2 == 0) {
        fore(p, cnt) if (p.second % 4) return NO;
        return YES;
    }
 
    if (H % 2 && W % 2) {
        map<int, int> c;
        fore(p, cnt) c[p.second % 4]++;
        if (c[3]) return NO;
        if (c[1] != 1) return NO;
        if (c[2] > (H - 1) / 2 + (W - 1) / 2) return NO;
        return YES;
    }
 
    if (W % 2) swap(H, W);
 
    map<int, int> c;
    fore(p, cnt) c[p.second % 4]++;
    if (c[1] || c[3]) return NO;
    if (c[2] > W / 2) return NO;
    return YES;
}
//--------------------------------------------------------------------------------------------------
void _main() {
    cin >> H >> W;
    rep(y, 0, H) cin >> A[y];
    cout << solve() << endl;
}