// Arup Guha
// 7/1/2012
// Solution to 2008 Southeast Regional Problem I: Teleport

import java.util.*;

public class i {

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);

		int r = stdin.nextInt();
		int c = stdin.nextInt();
		int casenum = 0;

		while (r != 0) {
			casenum++;

			// Read in grid.
			char[][] grid = new char[r][];
			for (int i=0; i<r; i++)
				grid[i] = stdin.next().toCharArray();

			int[][] notel = new int[r][c];

			// 0 = start, 1000000000 = not filled, 2000000000 = impossible
			for (int i=0; i<r; i++) {
				for (int j=0; j<c; j++) {

					if (grid[i][j] == '.' || grid[i][j] == 'Y')
						notel[i][j] = 1000000000;
					else if (grid[i][j] == 'X')
						notel[i][j] = 2000000000;
					else
						notel[i][j] = 0;

				}
			}

			// Find real shortest distances, without teleporting.
			fill(notel, grid);

			// Find the maximum distance in this grid.
			int max = getMax(notel);
			if (max == 0) max = 1;

			double mine = 1000000;

			// We will try all strategies of teleporting. Here, we try to teleport from all squares
			// that would take us i or more steps.
			for (int i=1; i<=max+1; i++) {

				double tempe = getE(notel, i);
				if (tempe < mine)
					mine = tempe;
			}

			// Get the answer for no teleporting also!
			double reg = 1000000;
			for (int i=0; i<r; i++)
				for (int j=0; j<c; j++)
					if (grid[i][j] == 'Y')
						reg = notel[i][j];

			// Print the best of the two.
			System.out.printf("%.3f\n", Math.min(mine, reg));

			r = stdin.nextInt();
			c = stdin.nextInt();
		}
	}

	// Figures out the expectation if our stategy is to teleport from all squares that are cutoff or farther away.
	public static double getE(int[][]notel, int cutoff) {

		// Basically we solve the following equation for T:
		// T = 1/n*(sum of each fixed option) + 1/n*(number of teleport squares)*(T+1)
		// The idea is that we have n places we could arrive from teleporting. With probability 1/n, we end up in each of
		// those spots. From some of those spots, we have a fixed number of steps to escape. But, from the rest, we just
		// wasted a step, so our expectation in these cases is T+1.

		int r = notel.length;
		int c = notel[0].length;

		// Keep track of illegal spots, number of spots off which we aren't teleporting and the sum of the
		// travel from those spots, plus 1.
		int cntX = 0, cntStay = 0, sumStay = 0;
		for (int i=0; i<r; i++) {
			for (int j=0; j<c; j++) {
				if (notel[i][j] == 2000000000)
					cntX++;
				else if (notel[i][j] < cutoff) {
					cntStay++;
					sumStay = sumStay + notel[i][j] + 1;
				}
			}
		}

		// n = number of places you could get teleported to.
		int n = r*c - cntX;

		// These are the places from which we will teleport.
		int numtele = n - cntStay;

		return (double)(sumStay + numtele)/cntStay;
	}

	// Returns the largest non-trivial value in notel.
	public static int getMax(int[][] notel) {

		int max = -1;
		int r = notel.length;
		int c = notel[0].length;

		for (int i=0; i<r; i++)
			for (int j=0; j<c; j++)
				if (max==-1 && notel[i][j] < 1000000000)
					max = notel[i][j];
				else if (notel[i][j] > max && notel[i][j] < 1000000000)
					max = notel[i][j];

		return max;
	}

	// Calculates real shortest distances, without teleporting.
	public static void fill(int[][] notel, char[][] grid) {

		int r = notel.length;
		int c = notel[0].length;

		while (true) {

			boolean flag = true;

			// Just update one move, by looking at the previous board and moving,
			// one step in each of the four directions. Most people would BFS here...
			for (int i=0; i<r; i++) {
				for (int j=0; j<c; j++) {

					if (grid[i][j] == 'Y') continue;
					if (grid[i][j] == 'X') continue;

					// Move up
					if (i-1>=0 && grid[i-1][j] != 'X') {
						if (notel[i][j] + 1 < notel[i-1][j]) {
							flag = false;
							notel[i-1][j] = notel[i][j]+1;
						}
					}

					// Move down
					if (i+1<r && grid[i+1][j] != 'X') {
						if (notel[i][j] + 1 < notel[i+1][j]) {
							flag = false;
							notel[i+1][j] = notel[i][j]+1;
						}
					}

					// Move left
					if (j-1 >= 0 && grid[i][j-1] != 'X') {
						if (notel[i][j] + 1 < notel[i][j-1]) {
							flag = false;
							notel[i][j-1] = notel[i][j]+1;
						}
					}

					// Move right
					if (j+1 < c && grid[i][j+1] != 'X') {
						if (notel[i][j] + 1 < notel[i][j+1]) {
							flag = false;
							notel[i][j+1] = notel[i][j]+1;
						}
					}
				}
			} // end i

			if (flag) break;
		}
	}
}