import java.io.*; import java.util.*; import java.awt.*; import java.text.*; class teleport_judge { public Scanner sc; public PrintStream ps; public String toString() { return "teleport_judge"; } // A single step - used for our BFS algorithm to determine shortest paths class Step { // Location (i,j) and number of steps to get here. public int i, j, nsteps; public Step( int ii, int jj, int ns ) { i=ii; j=jj; nsteps=ns; } public String toString() { return "{Step:i=" + i + ", j=" + j + ", nsteps=" + nsteps + "}"; } }; public void doit() throws Exception { sc = new Scanner( new File( "teleport.judge" ) ); ps = System.out; DecimalFormat df = new DecimalFormat( "0.000" ); for(;;) { // Read the limits, exit if this is the end. int n = sc.nextInt(); int m = sc.nextInt(); if( n==0 && m==0 ) break; // maze[][] will hold the maze - MaxInt will represent a wall, // otherwise, maze[i][j], will be the number of steps to the // exit, 99999 if you can't get there. int maze[][] = new int[n][m]; // Your starting position int si=0, sj=0; // This queue will be used later in the Breadth-First Search. // We need to declare it here, so we can put the exits on it // while reading them in. LinkedList queue = new LinkedList(); // Total number of traversable spaces. // We'll need this for the statistics later. // We'll count them while reading the maze in. int total = 0; // Read the maze for( int i=0; i0 ) { Step step = queue.removeFirst(); // Here's a new instance with this many steps - count it. ++counts[step.nsteps]; int i = step.i; int j = step.j; int ns = step.nsteps+1; // Try to take a step in each direction. // In each case there will be 3 tests: // - Does this step go off the maze? // - Does this step go into a wall? // - Does the destination already have a short path? // Only if it survives all 3 tests will be put it on the queue. // North if( i>0 && maze[i-1][j]ns ) { maze[i-1][j] = ns; queue.add( new Step( i-1, j, ns ) ); } // South if( ins ) { maze[i+1][j] = ns; queue.add( new Step( i+1, j, ns ) ); } // West if( j>0 && maze[i][j-1]ns ) { maze[i][j-1] = ns; queue.add( new Step( i, j-1, ns ) ); } // East if( jns ) { maze[i][j+1] = ns; queue.add( new Step( i, j+1, ns ) ); } } // Now, look for the best Expected Number of Steps if we jump. // We'll do this by adopting the rule "always jump if the distance is greater than x, // otherwise, never jump." The trick is now to find the optimal x // // We'll need to compute E(x), which is the expected number of steps with this strategy // for a given x. The Expected Value of anything is SUM[p(k)*v(k)] where p(k) is the // probability of k happening, and v(k) is the value of k. It only works if you've considered // all possible outcomes - that is, SUM[p(k)] = 1. // // If k<=x, and we're closer than x to the exit, then we walk straight there, and the number // of steps is k. if k>x, then we use our teleporter, which takes a step, and do the whole // thing again, so our expected number of steps would be 1+E(x). // // So, E(x) = p(0)*0 + p(1)*1 + p(2)*2 + p(3)*3 + ... + p(x)*x + p(k>x)*(1+E(x)) // // That's SUM[p(k)*k] + p(k>x)*(1+E(x)) // 0<=k<=x // // From now on, I'll use SUM to mean 'Sum from 0 to x', and get rid of that 0<=k<=x notation. // // OK, so what is p(k>x)? That's 1-p(k<=x). p(k<=x) is just p(0) + p(1) + p(2) + .... + p(x) // So, p(k>x) is 1-SUM[p(k)] // // Now, we have E(x) = SUM[p(k)*k] + (1-SUM[p(k)])*(1+E(x)) // E(x) is on both sides, but that's no problem. We can just do a little // algebra to solve, and end up with // // E(x) = (SUM[p(k)*k] + 1 - SUM[p(k)]) / SUM[p(k)] // // But what is p(k)? That's easy. The problem sez that every square is equally likely. // So, p(k) is the number of squares k away from the exit, divided by the total number of // open squares. Or, // // p(k) = counts[k]/total // We'll be looking for the best possible value. // Start with one that's unreasonably large. double bestjump = 100000.0; // Some sums we'll need for the stats // This is the sum of p(k)*k double sumpxx = 0.0; // This is the sum of p(k) double sumpx = 0.0; // Go through all possible x's for( int x=0; x<99999; x++ ) if( counts[x]>0 ) { // p(k) double prob = ((double)counts[x])/(double)total; // SUM[p(k)*k] sumpxx += prob*x; // SUM[p(k)] sumpx += prob; // E(x) double expected = (sumpxx + 1.0 - sumpx) / sumpx; if( expected < bestjump ) bestjump = expected; } // Now, just print the results. That's the best of either // going straight to the exit, or taking a step to teleport. ps.printf( "%.3f", Math.min( (double)maze[si][sj], 1.0+bestjump ) ); ps.println(); } } public static void main(String[] args) throws Exception { new teleport_judge().doit(); } }