Problem:
Score : 1400 points

Problem Statement

We have a grid with H rows and W columns.
The state of the cell at the i-th (1≤i≤H) row and j-th (1≤j≤W) column is represented by a letter a_{ij}, as follows:

. : This cell is empty.

o : This cell contains a robot.

E : This cell contains the exit. E occurs exactly once in the whole grid.

Snuke is trying to salvage as many robots as possible, by performing the following operation some number of times:

Select one of the following directions: up, down, left, right. All remaining robots will move one cell in the selected direction, except when a robot would step outside the grid, in which case the robot will explode and immediately disappear from the grid. If a robot moves to the cell that contains the exit, the robot will be salvaged and immediately removed from the grid.

Find the maximum number of robots that can be salvaged.

Constraints

2≤H,W≤100

a_{ij} is ., o or E.

E occurs exactly once in the whole grid.

Input

The input is given from Standard Input in the following format:

H W
a_{11}...a_{1W}
:
a_{H1}...a_{HW}

Output

Print the maximum number of robots that can be salvaged.

Sample Input 1

3 3
o.o
.Eo
ooo

Sample Output 1

3

For example, select left, up, right.

Sample Input 2

2 2
E.
..

Sample Output 2

0

Sample Input 3

3 4
o...
o...
oooE

Sample Output 3

5

Select right, right, right, down, down.

Sample Input 4

5 11
ooo.ooo.ooo
o.o.o...o..
ooo.oE..o..
o.o.o.o.o..
o.o.ooo.ooo

Sample Output 4

12

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

// package atcoder.agc.agc004;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class Main {
    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int h = in.nextInt();
        int w = in.nextInt();

        int ey = -1;
        int ex = -1;
        char[][] cmap = new char[h][];
        for (int i = 0; i < h ; i++) {
            cmap[i] = in.nextToken().toCharArray();
            for (int j = 0; j < w ; j++) {
                if (cmap[i][j] == 'E') {
                    ey = i;
                    ex = j;
                }
            }
        }

        imos = new int[h+1][w+1];
        for (int i = 0; i < h ; i++) {
            for (int j = 0; j < w ; j++) {
                imos[i+1][j+1] = imos[i+1][j] + imos[i][j+1] - imos[i][j] + ((cmap[i][j] == 'o') ? 1 : 0);
            }
        }

        int U = ey;
        int D = h - U - 1;
        int L = ex;
        int R = w - L - 1;

        int[][][][] dp = new int[U+1][D+1][L+1][R+1];
        for (int u = 0; u <= U ; u++) {
            for (int d = 0; d <= D; d++) {
                for (int l = 0; l <= L; l++) {
                    Arrays.fill(dp[u][d][l], -1);
                }
            }
        }
        dp[0][0][0][0] = 0;

        for (int u = 0; u <= U ; u++) {
            for (int d = 0; d <= D ; d++) {
                for (int l = 0; l <= L ; l++) {
                    for (int r = 0; r <= R ; r++) {
                        int base = dp[u][d][l][r];
                        if (base < 0) {
                            continue;
                        }
                        int tu = Math.max(ey-u, d);
                        int td = Math.min(ey+d, h-u-1);
                        int tl = Math.max(ex-l, r);
                        int tr = Math.min(ex+r, w-l-1);

                        if (u < U && d <= ey-u-1) {
                            dp[u+1][d][l][r] = Math.max(dp[u+1][d][l][r], base + inclusiveSum(ey-u-1, ey-u-1, tl, tr));
                        }
                        if (d < D && u <= (h-1)-(ey+d+1)) {
                            dp[u][d+1][l][r] = Math.max(dp[u][d+1][l][r], base + inclusiveSum(ey+d+1, ey+d+1, tl, tr));
                        }
                        if (l < L && r <= ex-l-1) {
                            dp[u][d][l+1][r] = Math.max(dp[u][d][l+1][r], base + inclusiveSum(tu, td, ex-l-1, ex-l-1));
                        }
                        if (r < R && l <= (w-1)-(ex+r+1)) {
                            dp[u][d][l][r+1] = Math.max(dp[u][d][l][r+1], base + inclusiveSum(tu, td, ex+r+1, ex+r+1));
                        }
                    }
                }
            }
        }

        int max = 0;
        for (int u = 0; u <= U ; u++) {
            for (int d = 0; d <= D; d++) {
                for (int l = 0; l <= L; l++) {
                    for (int r = 0; r <= R; r++) {
                        max = Math.max(max, dp[u][d][l][r]);
                    }
                }
            }
        }
        out.println(max);
        out.flush();
    }

    static int[][] imos;

    static int inclusiveSum(int u, int d, int l, int r) {
        if (u > d) {
            return 0;
        }
        if (l > r) {
            return 0;
        }
        return imos[d+1][r+1] - imos[d+1][l] - imos[u][r+1] + imos[u][l];
    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        private int[] nextInts(int n) {
            int[] ret = new int[n];
            for (int i = 0; i < n; i++) {
                ret[i] = nextInt();
            }
            return ret;
        }


        private int[][] nextIntTable(int n, int m) {
            int[][] ret = new int[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    ret[i][j] = nextInt();
                }
            }
            return ret;
        }

        private long[] nextLongs(int n) {
            long[] ret = new long[n];
            for (int i = 0; i < n; i++) {
                ret[i] = nextLong();
            }
            return ret;
        }

        private long[][] nextLongTable(int n, int m) {
            long[][] ret = new long[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    ret[i][j] = nextLong();
                }
            }
            return ret;
        }

        private double[] nextDoubles(int n) {
            double[] ret = new double[n];
            for (int i = 0; i < n; i++) {
                ret[i] = nextDouble();
            }
            return ret;
        }

        private int next() {
            if (numChars == -1)
                throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public char nextChar() {
            int c = next();
            while (isSpaceChar(c))
                c = next();
            if ('a' <= c && c <= 'z') {
                return (char) c;
            }
            if ('A' <= c && c <= 'Z') {
                return (char) c;
            }
            throw new InputMismatchException();
        }

        public String nextToken() {
            int c = next();
            while (isSpaceChar(c))
                c = next();
            StringBuilder res = new StringBuilder();
            do {
                res.append((char) c);
                c = next();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        public int nextInt() {
            int c = next();
            while (isSpaceChar(c))
                c = next();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = next();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c-'0';
                c = next();
            } while (!isSpaceChar(c));
            return res*sgn;
        }

        public long nextLong() {
            int c = next();
            while (isSpaceChar(c))
                c = next();
            long sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = next();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c-'0';
                c = next();
            } while (!isSpaceChar(c));
            return res*sgn;
        }

        public double nextDouble() {
            return Double.valueOf(nextToken());
        }

        public boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }

    static void debug(Object... o) {
        System.err.println(Arrays.deepToString(o));
    }
}