import java.io.*; import java.util.*; import java.awt.geom.*; /** * Solution to Magic Checkerboard * * @author vanb */ public class checkerboard_vanb { public Scanner sc; public PrintStream ps; // Cells that touch diagonally must differ in parity. // Let's look at a large checkerboard: // +-+-+-+-+-+-+-+-+-+-+ // |A|B|A|B|A|B|A|B|A|B| // +-+-+-+-+-+-+-+-+-+-+ // |C|D|C|D|C|D|C|D|C|D| // +-+-+-+-+-+-+-+-+-+-+ // |A|B|A|B|A|B|A|B|A|B| // +-+-+-+-+-+-+-+-+-+-+ // |C|D|C|D|C|D|C|D|C|D| // +-+-+-+-+-+-+-+-+-+-+ // |A|B|A|B|A|B|A|B|A|B| // +-+-+-+-+-+-+-+-+-+-+ // |C|D|C|D|C|D|C|D|C|D| // +-+-+-+-+-+-+-+-+-+-+ // Now, every A cell must have the same parity as every other A cell. // Every D cell must have the same parity as every other D cell, and must be the opposite of A. // Every B cell must have the same parity as every other B cell. // Every C cell must have the same parity as every other C cell, and must be the opposite of B. /** * This matrix represents the required parities. * parity[0][0] is A * parity[0][1] is B * parity[1][0] is C * parity[1][1] is D * * It'll hold -1 if unknown, 0 for even parity, 1 for odd parity. */ public static int parity[][] = { { -1, -1 }, { -1, -1 } }; /** * Get the parity at cell (i,j) * * @param i Row * @param j Column * @return Parity */ public static int getParity( int i, int j ) { return parity[i&1][j&1]; } /** * Set the parity at (i,j), and also set its diagonal to the opposite parity. * * @param i Row * @param j Column * @param p Parity */ public static void setParity( int i, int j, int p ) { // Set (i,j) parity[i&1][j&1] = p; // Set diagonal to the opposite parity parity[1-(i&1)][1-(j&1)] = 1-p; } /** Size of the board */ public int n, m; public long solve( int board[][], boolean useparity ) { int newboard[][] = new int[n][m]; boolean failed = false; long sum = 0; // Now, go through the board, test the increasing row & column constraint, // and generate the lowest possible number for each empty cell (where board[i][j]==0) for( int i=0; i0 ) c = newboard[i-1][j]+1; // If there's a cell above, make sure we're at least 1 bigger if( j>0 ) c = Math.max( c, newboard[i][j-1]+1 ); // Now, handle parity if( useparity && (c&1)!=getParity(i,j) ) ++c; // And, put this value in the board. newboard[i][j] = c; } else { // If this cell already has a value, // then just make sure it is bigger than the one to the left and the one above. if( i>0 && c<=newboard[i-1][j] ) failed = true; else if( j>0 && c<=newboard[i][j-1] ) failed = true; } // Add the value in the cell, whether already there or just computed, // to the sum sum += c; newboard[i][j] = c; } // System.err.println( sum ); // for( int i=0; i0 ) { int p = getParity(i,j); // If we don't know it yet, set it. // Otherwise, test to be sure we're consistent. if( p==-1 ) setParity(i,j,c&1); else if( p!=(c&1) ) failed = true; } board[i][j] = c; } long best = -1L; // If n==1 or m==1, then there are no diagonals. // The parity test cannot fail. if( n==1 || m==1 ) { best = solve( board, false ); } else if( !failed ) { if( getParity(0,0)<0 ) setParity(0,0,1); if( getParity(0,1)<0 ) { setParity(0,1,0); long sum0 = solve( board, true ); setParity(0,1,1); long sum1 = solve( board, true ); if( sum0<0 ) best = sum1; else if( sum1<0 ) best = sum0; else best = Math.min( sum0, sum1 ); } else { best = solve( board, true ); } } ps.println( best ); } public static void printboard( PrintStream ps, int b[][] ) throws Exception { ps.println( "" + b.length + " " + b[0].length ); for( int i=0; i