Codeforces 432(#246 Div2 only) E. Square Tiling
問題
hxwのグリッドの各マスをA-Zの文字いずれかで埋める。
隣り合う(辺を共有する)マスであって、同じ文字が書かれたタイルは繋がっているとする。
繋がったタイルの塊は必ず正方形をしていなければならない。
辞書順で最小の埋め方を求めよ。
制約条件
h, w≦100
方針
左上から順に埋める。
使えそうな文字のうち、辞書順で最小のものを見つける。
これが一個左隣のマスよりも大きかったら、一個左隣のマスの塊の正方形を1拡大したほうが得なので、それができないか確認してみる。
できるんだったら拡大する。そうでなければその辞書順最小のものを使えばよい。
ソースコード
const int dy[] = {-1, 0, 1, 0}, dx[] = {0, -1, 0, 1}; int h, w; string ans[100]; inline bool ok(int y, int x, char c){ rep(d, 4){ int ny = y + dy[d], nx = x + dx[d]; if(ny < 0 || nx < 0 || ny >= h || nx >= w) continue; if(ans[ny][nx] == c) return 0; } return 1; } inline bool ok2(int y, int x, char c){ if(ans[y][x] != '.') return 0; for(int d = 1; d < 4; d++){ int ny = y + dy[d], nx = x + dx[d]; if(ny < 0 || nx < 0 || ny >= h || nx >= w) continue; if(ans[ny][nx] == c) return 0; } return 1; } inline bool ok3(int y, int x, char c){ if(ans[y][x] != '.') return 0; rep(d, 4) if(d != 1){ int ny = y + dy[d], nx = x + dx[d]; if(ny < 0 || nx < 0 || ny >= h || nx >= w) continue; if(ans[ny][nx] == c) return 0; } return 1; } inline bool check(int y, int x){ int Y = y, X = x; while(y && ans[y - 1][x] == ans[y][x]) y--; while(x && ans[y][x - 1] == ans[y][x]) x--; while(Y + 1 < h && ans[Y + 1][X] == ans[Y][X]) Y++; while(X + 1 < w && ans[Y][X + 1] == ans[Y][X]) X++; if(Y + 1 >= h || X + 1 >= w) return 0; int l = Y - y + 2; rep(i, l) if(!ok2(Y + 1, x + i, ans[y][x]) || !ok3(y + i, X + 1, ans[y][x])) return 0; return 1; } void extend(int y, int x){ int Y = y, X = x; while(y && ans[y - 1][x] == ans[y][x]) y--; while(x && ans[y][x - 1] == ans[y][x]) x--; while(Y + 1 < h && ans[Y + 1][X] == ans[Y][X]) Y++; while(X + 1 < w && ans[Y][X + 1] == ans[Y][X]) X++; int l = Y - y + 2; rep(i, l) ans[Y + 1][x + i] = ans[y + i][X + 1] = ans[y][x]; } int main(){ cin >> h >> w; rep(i, h) ans[i] = string(w, '.'); rep(i, h) rep(j, w) if(ans[i][j] == '.'){ char p = j ? ans[i][j - 1] : 'Z', c = 'A'; for(; c < p; c++){ if(ok(i, j, c)) break; } if(c != p) ans[i][j] = c; else if(check(i, j - 1)) extend(i, j - 1); else for(c = p + 1; ; c++){ if(ok(i, j, c)){ ans[i][j] = c; break; } } } rep(i, h) cout << ans[i] << endl; return 0; }