/*
* Problem :: 2589 / 보물섬
*
* Kind :: BFS
*
* Insight
* - 보물은 서로 최단 거리로 이동하는데 있어 가장 긴 시간이 걸리는...
* + 최단 거리 => BFS, 가장 긴 시간 => 최단 거리로 이동할 때 가장 멀다
* 육지마다 BFS 를 돌려서 그 육지를 기준으로 가장 먼 육지까지의
* 최대 최단 거리(걸린 시간)가 답이다
* # 시간은 충분한가?
* 지도 넓이 = 50^2
* BFS 한번 = 50^2
* O(50^4) = O(6250000) < O(10^8) 이니
* 충분할 것 같다
*
* Point
* - 지도 가장자리거나 근처에 바다가 있는 육지가 아니면
* 그 육지는 보물이 묻혀있을 수 없다
* => 최대 최단 거리가 될려면 두 육지가 섬 내부가 아닌 바깥 경계에 있어야 하기 때문이다
*/
//
// BOJ
// ver.C++
//
// Created by GGlifer
//
// Open Source
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define endl '\n'
// Set up : Global Variables
int N, M;
char cato[50][50];
int dy[4] = {+1, 0, 0, -1};
int dx[4] = {0, +1, -1, 0};
struct Point { int y, x; };
// Set up : Functions Declaration
bool isValid(int y, int x);
bool isBoundary(int y, int x);
int bfs(int sy, int sx);
int main()
{
// Set up : I/O
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Set up : Input
cin >> N >> M;
for (int i=0; i<N; i++) {
for (int j=0; j<M; j++) {
cin >> cato[i][j];
}
}
// Process
int ans = -1;
for (int i=0; i<N; i++) {
for (int j=0; j<M; j++) {
if (cato[i][j] == 'L') { /* (i,j) 가 육지이고 */
if (isBoundary(i, j)) { /* 바깥 경계에 위치해있으면 */
ans = max(ans, bfs(i, j));
}
}
}
}
// Control : Output
cout << ans << endl;
}
// Helper Functions
bool isValid(int y, int x)
/* 좌표 (y,x) 가 유효하면 true 를 반환, 그 외 false 를 반환 */
{
return y >= 0 && y < N && x >= 0 && x < M;
}
bool isBoundary(int y, int x)
/* (y,x) 와 인접한 칸의 좌표가 유효하지 않거나 그 칸이 바다이면 true 를 반환
* 그 외 false 를 반환 */
{
for (int i=0; i<4; i++) {
int ay = y + dy[i];
int ax = x + dx[i];
if (not(isValid(ay, ax)) || cato[ay][ax] == 'W') {
return true;
}
}
return false;
}
int bfs(int sy, int sx)
/* (sy,sx) 에서 이동할 수 있는 모든 인접한 칸을 방문했을 때 걸린 총 이동 시간을 반환 */
{
queue<Point> que;
bool isVisited[N][M];
memset(isVisited, false, sizeof(isVisited));
que.push({sy, sx}); /* 시작 위치 */
isVisited[sy][sx] = true;
int time = -1; /* 총 이동 시간 */
while (not(que.empty())) {
int size = que.size(); /* 방문할 다음 칸들의 개수 */
time++; /* 그 칸들이 방문될 때까지 총 걸린 이동 시간 갱신 */
while (size--) {
int cy = que.front().y; /* 현재 방문한 칸의 y 좌표 */
int cx = que.front().x; /* 현재 방문한 칸의 x 좌표 */
que.pop();
for (int i=0; i<4; i++) {
int ny = cy + dy[i];
int nx = cx + dx[i];
/* 인접한 칸이 유효하고, 육지이며, 방문되지 않았다면 */
if (isValid(ny, nx) && cato[ny][nx] == 'L'
&& not(isVisited[ny][nx]))
{
/* 방문 처리 */
isVisited[ny][nx] = true;
que.push({ny, nx});
}
}
}
}
return time;
}