あまり綺麗な解法がない.全探索によるシュミレーションを高速化する問題.
基本は, 何を全探索するか. 升目の全探索は,削除の処理を考えると TLE である.
たとえば,
aaaaa
bcccc
bdeee
bdfgh
のような形が最悪ケース.
対策:
色が 26種類と少ないことを利用して, 色を全探索する方針. それを行と列に分けて,それぞれ行うが, まずは簡単のため,行と列の一方だけ考えるとよい.
注意
行を消したとき,対応する色の個数も減らす.
もう一つの注意は,行と列を同時に消すということ. 別々に消すと WA. 例えば,Input 2 の様に
aaaaa
abcde
の形が反例.行を先に消すと abcde の 5文字が残るが, 行と列を同時に消すと bcde の 4文字が残る.
使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"
int main() {
vll vh(2); cinv(vh);
vvvll cnt(2);
rep(i,2) cnt[i] = vvll(vh[i], vll(26));
rep(x, vh[0]) rep(y, vh[1]) {
ll c = s[x][y]-'a';
cnt[0][x][c]++;
cnt[1][y][c]++;
}
vvll del(2); rep(i,2) del[i] = vll(vh[i]);
vll rvh = vh;
while(true){
//
// rem: 行と列に同時に印をつけてから消す.
// そうしないと,たとえば行だけ先に消すと,
// 消したせいで 1行になってしまうことがる.
// 例:Input 2
// aaaaa
// abcde
// これは,行を先に消してしまうと 5つ残るが,
// 行と列を同時に消すと 4つ残る.
rep(k,2) rep(x, vh[k]) if(!del[k][x]){
rep(c,26){
buf.push_back({k,x,c});
}
}
}
if(buf.size()==0) break;
for(auto [k,x,c]: buf){
del[k][x] = true;
rvh[k]--;
rep(y, vh[k^1]) cnt[k^1][y][c]--; // rem: 実際に削除
}
}
cout << (rvh[0]*rvh[1]) << endl;
return 0;
}
*1:cnt[k][x][c] == rvh[k^1]) && (rvh[k^1] >=2