Problem:
Score : 600 points

Problem Statement

There is a board with N rows and M columns.
The information of this board is represented by N strings S_1,S_2,\ldots,S_N.
Specifically, the state of the square at the i-th row from the top and the j-th column from the left is represented as follows:

S_{i,j}=. : the square is empty.

S_{i,j}=# : an obstacle is placed on the square.

S_{i,j}=o : a piece is placed on the square.

Yosupo repeats the following operation:

Choose a piece and move it to its right adjecent square or its down adjacent square.
Moving a piece to squares with another piece or an obstacle is prohibited.
Moving a piece out of the board is also prohibited.

Yosupo wants to perform the operation as many times as possible.
Find the maximum possible number of operations.

Constraints

1 \leq N \leq 50

1 \leq M \leq 50

S_i is a string of length M consisting of ., # and o.

1 \leq ( the number of pieces )\leq 100.
In other words, the number of pairs (i, j) that satisfy S_{i,j}=o is between 1 and 100, both inclusive.

Input

Input is given from Standard Input in the following format:

N M
S_1
S_2
\vdots
S_N

Output

Print the maximum possible number of operations in a line.

Sample Input 1

3 3
o..
...
o.#

Sample Output 1

4

Yosupo can perform operations 4 times as follows:

o.. .o. ..o ... ...
... -> ... -> ... -> ..o -> ..o
o.# o.# o.# o.# .o#

Sample Input 2

9 10
.#....o#..
.#..#..##o
.....#o.##
.###.#o..o
#.#...##.#
..#..#.###
#o.....#..
....###..o
o.......o#

Sample Output 2

24

Solution in Java (OpenJDK 1.8.0) (judge verdict: Runtime Error)

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class Main {

	int[] X = new int[] { 1, 0 };
	int[] Y = new int[] { 0, 1 };

	private int DFS(int[][] board, Map<String, Integer> states, String currentState) {
		
		if (states.containsKey(currentState)) {
			return states.get(currentState);
		}
		
		
		int ans = 1;
		int n = board.length;
		int m = board[0].length;
		
		for(int i=0; i<n; i++) {
			for(int j=0; j<m; j++) {
				if (board[i][j] == 1) {
					
					for(int k=0; k<2; k++) {
						
						int nextI = i + X[k];
						int nextJ = j + Y[k];
						
						if (nextI >= 0 && nextI < n && nextJ >= 0 && nextJ < m && board[nextI][nextJ] == 0) {
							
							board[nextI][nextJ] = 1;
							board[i][j] = 0;
							
							StringBuilder nextState = new StringBuilder(currentState);
							nextState.setCharAt(nextI * n + nextJ, 'o');
							nextState.setCharAt(i*n + j, '.');
							ans = Math.max(ans, 1 + DFS(board, states, nextState.toString()));
							
							board[nextI][nextJ] = 0;
							board[i][j] = 1;
						}
					}
				}
			}
		}
		
		states.put(currentState, ans);
		return ans;
	}
	
	public void getNumberOfReachableCities(int input) throws Exception {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		if (input == 1) {
			br = new BufferedReader(new FileReader("test.txt"));
		}

		StringTokenizer st = new StringTokenizer(br.readLine(), " ");

		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());

		int[][] board = new int[n][m];
		String state = "";
		
		for (int i = 0; i < n; i++) {
			
			String row = br.readLine();
			for (int j = 0; j < m; j++) {
				if (row.charAt(j) == '#') {
					board[i][j] = -1;
				} else if (row.charAt(j) != '.') {
					board[i][j] = 1;
				}
			}
			
			state += row.trim();
		}

		Map<String, Integer> states = new HashMap<String, Integer>();
		System.out.println(DFS(board, states, state) - 1);
	}

	public static void main(String[] args) throws Exception {

		Main a = new Main();

		a.getNumberOfReachableCities(0);

	}
}