// Simple, TOTALLY inefficient backtracking. import java.util.*; import java.io.*; class Pair { public int r,c; public Pair(int r, int c) { this.r = r; this.c = c; } } public class SquaresRSR { public static int n,m; // # rows, # cols public static char grid[][]; public static int fixed; public static String lab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); n = Integer.parseInt(st.nextToken()); m = Integer.parseInt(st.nextToken()); grid = new char[n+2][m+2]; // Add boundary regions around the outside edges for (int i = 0; i < n; i++) { grid[i][0] = '#'; grid[i][m+1] = '#'; } for (int j = 0; j < m; j++) { grid[0][j] = '#'; grid[n+1][j] = '#'; } for (int i = 1; i <= n; i++) { String line = br.readLine(); for (int j = 1; j <= m; j++) { grid[i][j] = line.charAt(j-1); } } if (search(0)) { print(); } else { System.out.println("elgnatcer"); } } // Recursively fill in squares left to right, top to bottom: public static boolean search(int labl) { Pair p = findEmpty(); if (p==null) // we've filled everything--we're done! return true; //else We've found an unlabelled cell that isn't a wall. // Search down and right for '$', expand to smallest square containing // it and fill it. Pair dollar =treas(p.r,p.c); if (dollar==null) // no treasure for this room (so it's not really a room) return false; // Find dimensions of smallest square with upper left corner (p.r,p.c) // that contains (dollar.r,dollar.c): int width = Math.max(dollar.r-p.r+1,dollar.c-p.c+1); // Fill in this smallest possible square with current room label: for (int i=0; i < width; i++) for (int j = 0; j < width; j++) grid[p.r+i][p.c+j] = lab.charAt(labl); // Now try this square and all possible expansions of it: if (search(labl+1)) return true; // done int exp = width+1; while(p.r+exp-1 <= n && p.c+exp-1 <= m) { // use increasingly larger widths // make sure next col and row are free before we fill it in: boolean okay = true; for (int i = 0; i < exp; i++) { if (grid[p.r+i][p.c+exp-1] != '.') { okay = false; break; } if (grid[p.r+exp-1][p.c+i] != '.') { okay = false; break; } } if (!okay) { break; } // else we can expand this square to the next row and col: for (int i1 = 0; i1 < exp; i1++) { grid[p.r+i1][p.c+exp-1] = lab.charAt(labl); grid[p.r+exp-1][p.c+i1] = lab.charAt(labl); } if (search(labl+1)) return true; exp++; } //undo everything and return failure: for (int i1 = 0; i1 < exp-1; i1++) { for (int j1 = 0; j1 < exp-1; j1++) { grid[p.r+i1][p.c+j1] = '.'; } } grid[dollar.r][dollar.c] = '$'; return false; } // find first '$' southeast of current location (r,c), inclusive: public static Pair treas(int r, int c) { int width = 1; int di = -1, dj = -1; while(true) { int bottom = r+width-1; int right = c+width-1; if (bottom > n) return null; // ran off bottom edge if (right > m) return null; // ran off right edge int found = 0; // search down right column: for (int i = r; i < r+width; i++) { if (grid[i][right] == '$') { found++; // not done yet, however! di = i; dj = right; } else if (grid[i][right] != '.') return null; // hit rock or previous square } // search across bottom row for (int j = c; j < c+width-1; j++) { if (grid[bottom][j] == '$') { found++; di = bottom; dj = j; } else if (grid[bottom][j] != '.') return null; } if (found==1) return new Pair(di,dj); else if (found > 1) return null; else width++; } //return -1; } public static Pair findEmpty() { // Just a dumb search starting from (1,1): for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (grid[i][j] == '.' || grid[i][j] == '$') { return new Pair(i,j); } } } return null; } public static void print() { for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { System.out.print(grid[i][j]); } System.out.println(); } } }