import java.util.*; class Clue { public int r,c,num,len; public char dir; public double score; public Clue(int r, int c, int n, char d) { this.r = r; this.c = c; num = n; dir = d; score = 0; } } public class Punct_bob { public static Scanner in; public static int r,c; public static char grid[][]; public static String row[]; public static String col[]; public static ArrayList clue; public static double eps = 1.e-8; // allowance for score comparisons public static void main(String[] args) { // read in the data in = new Scanner(System.in); r = in.nextInt(); c = in.nextInt(); grid = new char[r][c]; row = new String[r]; col = new String[c]; Arrays.fill(col,""); for (int i = 0; i < r; i++) { row[i] = in.next(); for (int j = 0; j < c; j++) { grid[i][j] = row[i].charAt(j); col[j] += grid[i][j]; } } // Figure out where the clues are: clue = new ArrayList(); int cn = 1; for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { if (grid[i][j] == '#') continue; boolean ac = false, dn = false; if (j == 0 || (j > 0 && grid[i][j-1] == '#')) { // at a left edge clue.add(new Clue(i,j,cn,'A')); ac = true; } if (i == 0 || (i > 0 && grid[i-1][j] == '#')) { // at top edge clue.add(new Clue(i,j,cn,'D')); dn = true; } if (ac || dn) cn++; } } for (Clue cl:clue) { // find lengths and initial scores: int i = cl.r, j = cl.c; if (cl.dir=='A') { int t = row[i].substring(j).indexOf('#'); if (t >= 0) cl.len = t; else cl.len = c-j; double score = 0; for (int k = 0; k < cl.len; k++) { if (grid[i][j+k] != '.') {score += cl.len-k;} } cl.score = score/cl.len/(cl.len+1)*2; } else { // must be 'D' int t = col[j].substring(i).indexOf('#'); if (t >= 0) cl.len = t; else cl.len = r-i; double score = 0; for (int k = 0; k < cl.len; k++) { if (grid[i+k][j] != '.') {score += cl.len-k;} } cl.score = score/cl.len/(cl.len+1)*2; } } // Now iterate until done. sort(clue); int i = clue.size()-1; while (clue.size() > 0 && clue.get(i).score == 1.0) { clue.remove(i); i--; } while (clue.size() > 0) { Clue cl = clue.remove(clue.size()-1); System.out.println(cl.num+""+(char)cl.dir); // Fill in the clue: for (int k = 0; k < cl.len; k++) { if (cl.dir=='A') grid[cl.r][cl.c+k] = 'X'; else grid[cl.r+k][cl.c] = 'X'; } update(); sort(clue); int k = clue.size()-1; while (clue.size() > 0 && clue.get(k).score == 1.0) { clue.remove(k); k--; } } } public static void sort(ArrayList clue) { clue.sort(new Comparator() { public int compare(Clue c1, Clue c2) { if (c1.score < c2.score-eps) return -1; else if (c1.score > c2.score+eps) return 1; else { // equal scores; pick across if (c1.dir > c2.dir) return -1; // 'D' is less than 'A' else if (c1.dir < c2.dir) return 1; else { // need to add test for clue number if (c1.num > c2.num) return -1; // higher numbers are bad else return 1; } } }}); } public static void update() { for (Clue cl:clue) { // find lengths and scores: int i = cl.r, j = cl.c; if (cl.dir=='A') { double score = 0; for (int k = 0; k < cl.len; k++) { if (grid[i][j+k] != '.') {score += cl.len-k;} } cl.score = score/cl.len/(cl.len+1)*2; } else { // must be 'D' double score = 0; for (int k = 0; k < cl.len; k++) { if (grid[i+k][j] != '.') {score += cl.len-k;} } cl.score = score/cl.len/(cl.len+1)*2; } } } }