// Arup Guha
// 12/14/2017
// Solution to 2017 WF Problem: Pachinko

import java.util.*;
import java.io.*;

public class h {

	// For precision issues.
	final public static double MULT = 1000.0;

	// This is weird because of how I calculate my equations, it's backwards u/d and l/r are switched.
	final public static int[] DX = {1,-1,0,0,0};
	final public static int[] DY = {0,0,1,-1,0};

	// Because I want to create my terms in this order. This accesses what is above.
	final public static int[] perm = {1,3,4,2,0};

	// This is for adjusting probabilities coming "out of" a square.
	final public static int[] permOut = {1,0,3,2};

	// Store the data.
	public static int c;
	public static int r;
	public static int n;
	public static char[][] grid;
	public static double[] prob;

	// How many items on the top are open.
	public static int topOpen;

	// This is what we divide each probability out of each square by (normalizing them)...
	public static double[][] divFactor;

	public static void main(String[] args) throws Exception {

		// Get all of the raw input.
		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());
		c = Integer.parseInt(tok.nextToken());
		r = Integer.parseInt(tok.nextToken());
		n = c*r;
		tok = new StringTokenizer(stdin.readLine());
		prob = new double[4];
		for (int i=0; i<4; i++)
			prob[i] = Integer.parseInt(tok.nextToken())/100.0;
		grid = new char[r][];
		for (int i=0; i<r; i++)
			grid[i] = stdin.readLine().trim().toCharArray();

		// Precomputation of a division factor for moving from each square.
		divFactor = new double[r][c];
		for (int i=0; i<r; i++) {
			for (int j=0; j<c; j++) {
				divFactor[i][j] = 0;
				if (grid[i][j] != '.') continue;

				// Try going in all directions.
				for (int k=0; k<4; k++) {

					int nx = i + DX[k];
					int ny = j + DY[k];

					// Also doesn't count.
					if (!inbounds(nx, ny)) continue;
					if (grid[nx][ny] == 'X') continue;

					// Add this to our division factor.
					divFactor[i][j] += prob[permOut[k]];
				}
			}
		}

		// Calculate the number of openings at the top.
		topOpen = 0;
		for (int i=0; i<c; i++)
			if (grid[0][i] == '.')
				topOpen++;

		// Will store all equations here.
		eqn[] all = new eqn[n];
		for (int i=0; i<n; i++)
			all[i] = makeEqn(i);

		// Set up and solve equations.
		sparseeqn myeqns = new sparseeqn(all);
		myeqns.LTForm();
		double[] res = myeqns.solve();

		// Calculate our division factor.
		double div = 0;
		for (int i=0; i<r; i++)
			for (int j=0; j<c; j++)
				if (grid[i][j] == 'T')
					div += res[i*c+j];

		// Output result.
		for (int i=0; i<r; i++)
			for (int j=0; j<c; j++)
				if (grid[i][j] == 'T')
					System.out.printf("%.9f\n", (res[i*c+j]/div));
	}

	// Make the equation for variable i.
	public static eqn makeEqn(int i) {

		// x is u/d, y is l/r.
		int x = i/c;
		int y = i%c;

		ArrayList<term> list = new ArrayList<term>();

		// Easiest to take care of.
		if (grid[x][y] == 'X') {
			list.add(new term(i, 1));
			return new eqn(list, 0);
		}

		// Go to all neighboring squares we could have come from.
		for (int z=0; z<5; z++) {

			int idx = perm[z];
			int nx = x + DX[idx];
			int ny = y + DY[idx];

			// Self term.
			if (nx == x && ny == y) {
				list.add(new term(i, 1*MULT));
				continue;
			}

			// Do not contribute to this term.
			if (!inbounds(nx, ny)) continue;
			if (grid[nx][ny] != '.') continue;

			// Variable number - add its contribution.
			int varNum = nx*c + ny;
			list.add(new term(varNum, -MULT*prob[idx]/divFactor[nx][ny]));
		}

		// Top Row affects constant term.
		if (x == 0) return new eqn(list, MULT*1.0/topOpen);

		// All other rows are like this.
		return new eqn(list, 0);
	}

	public static boolean inbounds(int x, int y) {
		return x >= 0 && x < r && y >= 0 && y < c;
	}
}

class sparseeqn {

	final public static boolean DEBUG = false;

	public int n;
	public eqn[] eqns;
	public ArrayList[] minMap;

	public sparseeqn(eqn[] myeqns) {
		eqns = myeqns;
		n = eqns.length;

		// minMap of i stores each equation number that has minimum value variable i.
		minMap = new ArrayList[n];
		for (int i=0; i<n; i++)
			minMap[i] = new ArrayList<Integer>();

		// Just go through and add each of these.
		for (int i=0; i<n; i++)
			minMap[eqns[i].minT].add(i);
	}

	public void LTForm() {

		// i is the variable we wish to eliminate from all but 1 equation.
		for (int i=0; i<n; i++) {

			// No equations or 1 with this variable, we are good.
			if (minMap[i].size() < 2) continue;

			// Find best equation to use to subtract from all of the others.
			int best = -1;
			for (int j=0; j<minMap[i].size(); j++) {
				int eqnNum = (Integer)(minMap[i].get(j));
				if (best == -1 || Math.abs(eqns[eqnNum].list.get(0).coeff) > Math.abs(eqns[best].list.get(0).coeff) )
					best = eqnNum;
			}

			// This is the Gaussian Elimination, subtract best from all of the rest.
			for (int j=minMap[i].size()-1; j>=0; j--) {

				// which equation we are talking about.
				int eqnNum = (Integer)(minMap[i].get(j));
				if (eqnNum == best) continue;

				// This is the minMap management since this equation is changing.
				minMap[i].remove(j);
				eqn newe = eqns[eqnNum].subOut(eqns[best]);
				eqns[eqnNum] = newe;
				minMap[newe.minT].add(eqnNum);
			}
		}
	}

	public double[] solve() {

		// Store all answers here.
		double[] res = new double[n];

		// We go backwards in this phase.
		for (int i=n-1; i>=0; i--) {

			// No equation has this as the min.
			if (minMap[i].size() == 0) continue;

			// Find the relevant equation.
			res[i] = eqns[(Integer)(minMap[i].get(0))].solve(res);
		}

		return res;
	}
}

class eqn {

	public double c;
	public ArrayList<term> list;
	public int minT;

	public eqn(ArrayList<term> myl, double myc) {
		list = myl;
		c = myc;
		if (list.size() == 0)
			minT = 0;
		else
			minT = list.get(0).var;
	}

	// Back subs for min term in this equation assuming res stores values of all future vars.
	public double solve(double[] res) {
		double myc = c;
		for (int i=1; i<list.size(); i++)
			myc -= (list.get(i).coeff*res[list.get(i).var]);

		if (list.get(0).coeff == 0)
			return 0;
		else
			return myc/list.get(0).coeff;
	}

	// Pre-req this.minT == other.minT.
	public eqn subOut(eqn other) {

		// Store result here.
		ArrayList<term> res = new ArrayList<term>();

		double factor = this.list.get(0).coeff/other.list.get(0).coeff;

		// i = index this, j = index other.
		int i = 0, j = 0;
		while (i < this.list.size() || j < other.list.size()) {


			// Only term in this - remains unchanged.
			if (j == other.list.size() || (i < this.list.size() && this.list.get(i).var < other.list.get(j).var)) {
				res.add(this.list.get(i));
				i++;
			}

			// Only term in other - mult by factor and negate.
			else if (i == this.list.size() || other.list.get(j).var < this.list.get(i).var) {
				double newc = -factor*other.list.get(j).coeff;
				if (Math.abs(newc) > 1e-9) res.add(new term(other.list.get(j).var, newc));
				j++;
			}

			// Both appear - don't add a 0 term.
			else {
				double newc = this.list.get(i).coeff - factor*other.list.get(j).coeff;
				if (Math.abs(newc) > 1e-9) res.add(new term(this.list.get(i).var, newc));
				i++;
				j++;
			}
		}

		// This is our new equation.
		return new eqn(res, this.c-factor*other.c);
	}
}

class term {

	public int var;
	public double coeff;

	public term(int v, double c) {
		var = v;
		coeff = c;
	}

	public String toString() {
		return coeff + "v" + var;
	}
}