// David Poeschl import java.util.Scanner; import java.util.LinkedList; public class VinDiagramsDavid { public static void main(String[] args) throws Exception { Scanner scan = new Scanner(System.in); int rows = scan.nextInt(); int cols = scan.nextInt(); char[][] diagram = new char[rows+2][cols+2]; for (int i = 0; i < cols + 2; i++) { diagram[0][i] = '.'; diagram[rows + 1][i] = '.'; } for (int rowNum = 1; rowNum <= rows; rowNum++) { diagram[rowNum][0] = '.'; diagram[rowNum][cols+1] = '.'; char[] row = scan.next().toCharArray(); for (int i = 1; i <= cols; i++) { diagram[rowNum][i] = row[i - 1]; } } floodfill(diagram, new Position(0, 0), 'O'); fillLoop(diagram, findPosition(diagram, 'A'), 'A'); fillLoop(diagram, findPosition(diagram, 'B'), 'B'); System.out.print(floodfill(diagram, findPositionInside(diagram, 'A'), 'A') + " "); System.out.print(floodfill(diagram, findPositionInside(diagram, 'B'), 'B') + " "); System.out.println(floodfill(diagram, findPosition(diagram, '.'), 'Z')); scan.close(); } private static Position findPositionInside(char[][] diagram, char target) throws Exception { for (int r = 1; r < diagram.length - 1; r++) { for (int c = 1; c < diagram[0].length - 1; c++) { if (diagram[r][c] == target) { if (diagram[r + 1][c] == 'O' && diagram[r - 1][c] == '.') return new Position(r - 1, c); if (diagram[r - 1][c] == 'O' && diagram[r + 1][c] == '.') return new Position(r + 1, c); if (diagram[r][c + 1] == 'O' && diagram[r][c - 1] == '.') return new Position(r, c - 1); if (diagram[r][c - 1] == 'O' && diagram[r][c + 1] == '.') return new Position(r, c + 1); } } } throw new Exception(); } private static void fillLoop(char[][] diagram, Position startPosition, char fillChar) { LinkedList queue = new LinkedList(); queue.add(startPosition); diagram[startPosition.r][startPosition.c] = 'X'; while (queue.peek() != null) { Position p = queue.remove(); if (diagram[p.r][p.c] == fillChar) continue; diagram[p.r][p.c] = fillChar; fillLoopHelper(diagram, queue, p, 1, 0); fillLoopHelper(diagram, queue, p, -1, 0); fillLoopHelper(diagram, queue, p, 0, 1); fillLoopHelper(diagram, queue, p, 0, -1); } } private static void fillLoopHelper(char[][] diagram, LinkedList queue, Position p, int deltaR, int deltaC) { if (diagram[p.r + deltaR][p.c + deltaC] == 'X') { if (isIntersection(diagram, p.r + deltaR, p.c + deltaC)) queue.add(new Position(p.r + 2 * deltaR, p.c + 2 * deltaC)); else queue.add(new Position(p.r + deltaR, p.c + deltaC)); } } private static boolean isIntersection(char[][] diagram, int r, int c) { if ((diagram[r + 1][c] == 'X' || diagram[r + 1][c] == 'A' || diagram[r + 1][c] == 'B') && (diagram[r - 1][c] == 'X' || diagram[r - 1][c] == 'A' || diagram[r - 1][c] == 'B') && (diagram[r][c + 1] == 'X' || diagram[r][c + 1] == 'A' || diagram[r][c + 1] == 'B') && (diagram[r][c - 1] == 'X' || diagram[r][c - 1] == 'A' || diagram[r][c - 1] == 'B')) { return true; } return false; } private static Position findPosition(char[][] diagram, char target) throws Exception { for (int r = 0; r < diagram.length; r++) for (int c = 0; c < diagram[0].length; c++) if (diagram[r][c] == target) return new Position(r, c); throw new Exception(); } private static int floodfill(char[][] diagram, Position startPosition, char floodChar) { LinkedList queue = new LinkedList(); queue.add(startPosition); int numPositionsFilled = 0; while (queue.peek() != null) { Position p = queue.remove(); if (diagram[p.r][p.c] != '.') { continue; } numPositionsFilled++; diagram[p.r][p.c] = floodChar; if (p.r > 0 && diagram[p.r - 1][p.c] == '.') queue.add(new Position(p.r - 1, p.c)); if (p.c > 0 && diagram[p.r][p.c - 1] == '.') queue.add(new Position(p.r, p.c - 1)); if (p.r < diagram.length - 1 && diagram[p.r + 1][p.c] == '.') queue.add(new Position(p.r + 1, p.c)); if (p.c < diagram[0].length - 1 && diagram[p.r][p.c + 1] == '.') queue.add(new Position(p.r, p.c + 1)); } return numPositionsFilled; } private static class Position { int r; int c; public Position(int r, int c) { this.r = r; this.c = c; } } }