Problem:
Score: 400 points

Problem statement

We have an H \times W grid whose squares are painted black or white. The square at the i-th row from the top and the j-th column from the left is denoted as (i, j).

Snuke would like to play the following game on this grid. At the beginning of the game, there is a character called Kenus at square (1, 1). The player repeatedly moves Kenus up, down, left or right by one square. The game is completed when Kenus reaches square (H, W) passing only white squares.

Before Snuke starts the game, he can change the color of some of the white squares to black. However, he cannot change the color of square (1, 1) and (H, W). Also, changes of color must all be carried out before the beginning of the game.

When the game is completed, Snuke's score will be the number of times he changed the color of a square before the beginning of the game. Find the maximum possible score that Snuke can achieve, or print -1 if the game cannot be completed, that is, Kenus can never reach square (H, W) regardless of how Snuke changes the color of the squares.

The color of the squares are given to you as characters s_{i, j}. If square (i, j) is initially painted by white, s_{i, j} is .; if square (i, j) is initially painted by black, s_{i, j} is #.

Constraints

H is an integer between 2 and 50 (inclusive).

W is an integer between 2 and 50 (inclusive).

s_{i, j} is . or # (1 \leq i \leq H, 1 \leq j \leq W).

s_{1, 1} and s_{H, W} are ..

Input

Input is given from Standard Input in the following format:

H W
s_{1, 1}s_{1, 2}s_{1, 3} ... s_{1, W}
s_{2, 1}s_{2, 2}s_{2, 3} ... s_{2, W}
: :
s_{H, 1}s_{H, 2}s_{H, 3} ... s_{H, W}

Output

Print the maximum possible score that Snuke can achieve, or print -1 if the game cannot be completed.

Sample Input 1

3 3
..#
#..
...

Sample Output 1

2

The score 2 can be achieved by changing the color of squares as follows:

Sample Input 2

10 37
.....................................
...#...####...####..###...###...###..
..#.#..#...#.##....#...#.#...#.#...#.
..#.#..#...#.#.....#...#.#...#.#...#.
.#...#.#..##.#.....#...#.#.###.#.###.
.#####.####..#.....#...#..##....##...
.#...#.#...#.#.....#...#.#...#.#...#.
.#...#.#...#.##....#...#.#...#.#...#.
.#...#.####...####..###...###...###..
.....................................

Sample Output 2

209

Solution in C (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 内部定数
#define D_MASS_MAX		50										// 最大マスサイズ
#define D_MASS_WHITE	'.'										// マス - 白
#define D_MASS_BLACK	'#'										// マス - 黒
#define D_STACK_KIND	2										// スタック種類
#define D_STACK_NO1		0										// スタック１
#define D_STACK_NO2		1										// スタック２

// 内部構造体 - 位置情報
typedef struct Pos {
	int miX, miY;												// 座標 0～
} Pos;

// 内部変数
static int siH;													// 高さ
static int siW;													// 幅
static char sc2Mass[D_MASS_MAX][D_MASS_MAX + 5];				// マス
static int si2Len[D_MASS_MAX][D_MASS_MAX + 5];					// 移動距離
static Pos sz2Pos[D_STACK_KIND][D_MASS_MAX * 2];				// 移動距離算出用スタック
static int si1PCnt[D_STACK_KIND];								// 移動距離算出用スタック数
static int siFNo;												// スタック位置 - 元
static int siTNo;												// スタック位置 - 先

// 内部変数 - テスト用
#ifdef D_TEST
	static int siRes;
	static FILE *szpFpT, *szpFpA;
#endif

// 移動距離セット - １マス
int
fSetLenOne(
	int piX						// <I> 位置X 0～
	, int piY					// <I> 位置Y 0～
	, int piLen					// <I> 移動距離
)
{
	// 範囲チェック
	if (piX < 0 || siW <= piX) {
		return 0;
	}
	if (piY < 0 || siH <= piY) {
		return 0;
	}

	// 移動可能チェック
	if (sc2Mass[piY][piX] != D_MASS_WHITE) {	// 白以外
		return 0;
	}

	// 移動距離チェック
	if (piLen >= si2Len[piY][piX]) {			// 既に到達済
		return 0;
	}

	// 移動距離セット
	si2Len[piY][piX] = piLen;

	// スタック
	sz2Pos[siTNo][si1PCnt[siTNo]].miX = piX;
	sz2Pos[siTNo][si1PCnt[siTNo]].miY = piY;
	si1PCnt[siTNo]++;

	return 0;
}

// 移動距離セット
int
fSetLen(
)
{
	int i, j, liLen;

	// 移動距離初期化
	for (i = 0; i < siH; i++) {
		for (j = 0; j < siW; j++) {
			si2Len[i][j] = INT_MAX;
		}
	}

	// 初期スタック
	siFNo = D_STACK_NO1;
	siTNo = D_STACK_NO2;
	memset(si1PCnt, 0, sizeof(si1PCnt));
	fSetLenOne(0, 0, 0);

	for (liLen = 1; ; liLen++) {

		// 元と先を変更
		if (siFNo == D_STACK_NO1) {
			siFNo = D_STACK_NO2;
			siTNo = D_STACK_NO1;
		}
		else {
			siFNo = D_STACK_NO1;
			siTNo = D_STACK_NO2;
		}

		// スタック数(先)
		si1PCnt[siTNo] = 0;

		// スタック数(元)でループ
		for (i = 0; i < si1PCnt[siFNo]; i++) {
			int liX = sz2Pos[siFNo][i].miX;
			int liY = sz2Pos[siFNo][i].miY;
			fSetLenOne(liX + 1, liY, liLen);	// 右
			fSetLenOne(liX - 1, liY, liLen);	// 左
			fSetLenOne(liX, liY + 1, liLen);	// 下
			fSetLenOne(liX, liY - 1, liLen);	// 上
		}

		// 終了チェック
		if (si2Len[siH - 1][siW - 1] != INT_MAX) {
			return 0;
		}
	}

	return 0;
}

// 最短ルートを黒化
int
fSetBlack(
	int piX						// <I> 位置X 0～
	, int piY					// <I> 位置Y 0～
	, int piLen					// <I> 移動距離
)
{
	int liRet;

	// 範囲チェック
	if (piX < 0 || siW <= piX) {
		return -1;
	}
	if (piY < 0 || siH <= piY) {
		return -1;
	}

	// 移動距離チェック
	if (piLen != si2Len[piY][piX]) {	// 最短ルート外
		return -1;
	}

	// 黒化
	sc2Mass[piY][piX] = D_MASS_BLACK;

	// 終了チェック
	if (piX == 0) {
		if (piY == 0) {
			return 0;
		}
	}

	// 右へ
	liRet = fSetBlack(piX + 1, piY, piLen - 1);
	if (liRet == 0) {
		return 0;
	}

	// 左へ
	liRet = fSetBlack(piX - 1, piY, piLen - 1);
	if (liRet == 0) {
		return 0;
	}

	// 下へ
	liRet = fSetBlack(piX, piY + 1, piLen - 1);
	if (liRet == 0) {
		return 0;
	}

	// 上へ
	liRet = fSetBlack(piX, piY - 1, piLen - 1);
	if (liRet == 0) {
		return 0;
	}

	return -1;
}

// スコア取得
int
fGetScore(
)
{
	int i, j;

	// 移動距離セット
	fSetLen();

	// 最短ルートを黒化
	fSetBlack(siW - 1, siH - 1, si2Len[siH - 1][siW - 1]);

	// 残った白数取得
	int liCnt = 0;
	for (i = 0; i < siH; i++) {
		for (j = 0; j < siW; j++) {
			if (sc2Mass[i][j] == D_MASS_WHITE) {
				liCnt++;
			}
		}
	}

	return liCnt;
}

// 実行メイン
int
fMain(
	int piTNo					// <I> テスト番号 1～
)
{
	int i;
	char lc1Buf[1024], lc1Out[1024];

	// テストファイルオープン
#ifdef D_TEST
	sprintf(lc1Buf, ".\\Test\\T%d.txt", piTNo);
	szpFpT = fopen(lc1Buf, "r");
	sprintf(lc1Buf, ".\\Test\\A%d.txt", piTNo);
	szpFpA = fopen(lc1Buf, "r");
	siRes = 0;
#endif

	// 高さ・幅取得
#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpT);
#else
	fgets(lc1Buf, sizeof(lc1Buf), stdin);
#endif
	sscanf(lc1Buf, "%d%d", &siH, &siW);
	
	// マス取得
	for (i = 0; i < siH; i++) {
#ifdef D_TEST
		fgets(sc2Mass[i], sizeof(sc2Mass[i]), szpFpT);
#else
		fgets(sc2Mass[i], sizeof(sc2Mass[i]), stdin);
#endif
	}

	// スコア取得
	int liScore = fGetScore();

	// 結果セット
	sprintf(lc1Out, "%d\n", liScore);

	// 結果表示
#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, lc1Out)) {
		siRes = -1;
	}
#else
	printf("%s", lc1Out);
#endif

	// テストファイルクローズ
#ifdef D_TEST
	fclose(szpFpT);
	fclose(szpFpA);
#endif

	// テスト結果
#ifdef D_TEST
	if (siRes == 0) {
		printf("OK %d\n", piTNo);
	}
	else {
		printf("NG %d\n", piTNo);
	}
#endif

	return 0;
}

int
main()
{

#ifdef D_TEST
	int i;
	for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {
		fMain(i);
	}
#else
	fMain(0);
#endif

	return 0;
}