/** Solution to "The Worm Turns" */ import java.util.*; public class Worm { public static Scanner in; // input public static final int FOOD=0, EMPTY=1, ROCK=2; public static int m, n; // # of rows and columns public static int b; // number of obstacles public static int[][] maze; // the maze public static int numFill; // number of spaces left to cover public static int bestRow, bestCol, bestDir, bestAnswer; // answer public static int prevBest; public static void main(String[] args) { in = new Scanner(System.in); int caseNum = 0; while (true) { // Read in the problem: // Dimensions of maze: m = in.nextInt(); n = in.nextInt(); if (m == 0 && n == 0) break; caseNum++; // Create maze: maze = new int[m][n]; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) maze[i][j] = FOOD; // Read in locations of rocks: b = in.nextInt(); for (int i = 0; i < b; i++) { int r = in.nextInt(); int c = in.nextInt(); maze[r][c] = ROCK; } // Get ready... boolean solved = false; int solrow = 0, solcol = 0; // solution row, column bestRow = 0; bestCol = 0; bestDir = 0; bestAnswer = 0; int soldir = 0; // solution direction numFill = m*n-b; prevBest = 0; // Try all possible starting locations and directions for solution: int rowInc[] = {0,-1,1,0}; int colInc[] = {1,0,0,-1}; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { for (int dir = 0; dir < 4; dir++) { if (maze[i][j] == FOOD) { // First, make sure there is food in the adjacent cell: if (!hasFood(i+rowInc[dir],j+colInc[dir])) continue; // skip to next direction maze[i][j] = EMPTY; numFill--; solved = solve(i,j,dir); if (solved) { bestAnswer = m*n-b; bestDir = dir; bestRow=i; bestCol=j; break; } if (bestAnswer > prevBest) { prevBest = bestAnswer; bestDir = dir; bestRow=i; bestCol=j; } maze[i][j] = FOOD; numFill++; } } // No need to continue searching if optimal solution found: if (solved) { break; } } // No need to continue searching if optimal solution found: if (solved) { break; } } System.out.print("Case " + caseNum + ": "); // printMaze(); if (bestAnswer == m*n-b) { System.out.printf("%d %d %d %s\n", bestAnswer, bestRow,bestCol,decode(bestDir)); // System.out.printf(" Perfect solution -- row %d, column %d, direction %s\n", // bestRow,bestCol,decode(bestDir)); } else System.out.printf("%d %d %d %s\n", bestAnswer, bestRow,bestCol,decode(bestDir)); } } public static void printMaze(){ for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) System.out.printf("%d",maze[i][j]); System.out.println(); } } public static String decode(int dir) { switch (dir) { case 0: return "E"; case 1: return "N"; case 2: return "S"; case 3: return "W"; } return ""; } // Enter a new cell: public static boolean solve(int row, int col, int dir) { //System.out.println("row = " + row + ", col = " + col + ", dir = " + decode(dir)); // if (numFill == 0) // we've found a perfect solution // return true; // Keep going as far as possible in the same direction: int count = 0; switch (dir) { case 0: // EAST: while (col+1 < n && maze[row][col+1] == FOOD) { col++; maze[row][col] = EMPTY; numFill--; count++; } break; case 1: // NORTH: while (row-1 >= 0 && maze[row-1][col] == FOOD) { row--; maze[row][col] = EMPTY; numFill--; count++; } break; case 2: // SOUTH: while (row+1 < m && maze[row+1][col] == FOOD) { row++; maze[row][col] = EMPTY; numFill--; count++; } break; case 3: // WEST: while (col-1 >= 0 && maze[row][col-1] == FOOD) { col--; maze[row][col] = EMPTY; numFill--; count++; } break; } //printMaze(); // row, col are now the location of the last cell visited // count indicates the number of cells travelled in direction dir, // not including the starting cell. //try every direction for extending the path boolean stuck = true; for (int d = 0; d < 4; d++) { int newrow = row, newcol = col; switch(d) { case 0: newcol++; break; case 1: newrow--; break; case 2: newrow++; break; case 3: newcol--; break; } if (newrow < 0 || newrow >= m || newcol < 0 || newcol >= n) continue; boolean solved = false; if (maze[newrow][newcol] == FOOD) { stuck = false; maze[newrow][newcol] = EMPTY; numFill--; solved = solve(newrow,newcol,d); if (solved) return true; numFill++; maze[newrow][newcol] = FOOD; } } if (stuck) { // we were unable to extend the path any further, so // update "bestAnswer" if (numFill == 0) return true; if (m*n-b-numFill > bestAnswer) bestAnswer = m*n-b-numFill; } // undo this move: switch(dir) { case 0: //EAST while (count > 0) { maze[row][col] = 0; col--; numFill++; count--; } break; case 1: //NORTH while (count > 0) { maze[row][col] = 0; row++; numFill++; count--; } break; case 2: // SOUTH while (count > 0) { maze[row][col] = 0; row--; numFill++; count--; } break; case 3: // WEST while (count > 0) { maze[row][col] = 0; col++; numFill++; count--; } break; } // nothing led to a solution return false; } public static boolean hasFood(int r, int c) { if (r < 0 || r >= m || c < 0 || c >= n) return false; return maze[r][c] == FOOD; } }