//============================================================================
// Name        : ACM.cpp
// Author      : Tarango Khan
// Copyright   : All Rights Reserved By Team Byteheads
// Description : !!!Hello World!!!
//============================================================================

#include <bits/stdc++.h>
#include <stdio.h>
#include <cstring>
using namespace std;
#define Pi 3.14159265359
#define Max 9999999
#define start_pos 15

int N;

char M[22][22];
int row, col;
int dx[] = { 1, -1, 0, 0, 1, -1, 1, -1 };
int dy[] = { 0, 0, 1, -1, -1, 1, 1, -1 };
int food = 0, sx, sy;

int Set(int N, int pos) {
	return N = N | (1 << pos);
}
bool Check(int N, int pos) {
	return (bool) (N & (1 << pos));
}
map<int, pair<int, int> > Map;
int total_nut = 0;

int isValid(int r, int c) {
	if (r < 0 || c < 0 || r >= row || c >= col){
		return 0;
	}
	return 1;
}

struct point {
	int x;
	int y;
	int cnt;
	point(int a, int b, int c) {
		x = a;
		y = b;
		cnt = c;
	}
};

int taken[22][22];
int shortest_Path(int sR, int sC, int tR, int tC) {
	memset(taken, 0, sizeof(taken));
	queue<point> Q;
	Q.push(point(sR, sC, 0));
	taken[sR][sC] = 1;

	while (Q.empty() == false) {
		point cur = Q.front();
		Q.pop();
		if (cur.x == tR && cur.y == tC) {
			return cur.cnt;
		}
		for (int i = 0; i < 8; i++) {
			int xx = cur.x + dx[i];
			int yy = cur.y + dy[i];

			if (isValid(xx, yy) == 1 && taken[xx][yy] == 0) {
				taken[xx][yy] = 1;
				Q.push(point(xx, yy, cur.cnt + 1));
			}
		}
	}
	return 0;
}

int distances[17][17];

void calculate_path() {
	for (int i = 0; i < total_nut; i++) {
		for (int j = 0; j < total_nut; j++) {
			distances[i][j] = distances[j][i] = shortest_Path(Map[i].first,
					Map[i].second, Map[j].first, Map[j].second);
		}
		distances[i][15] = distances[15][i] = shortest_Path(Map[i].first,Map[i].second, sx, sy);
	}
}

int DP[70000][17];

int call(int mask, int r, int c, int pos) {
	//printf("Currently at row: %d , col: %d mask: %d\n",r,c,mask);
	if (mask == (1 << total_nut) - 1) {
		int ed = distances[pos][start_pos];
		//printf("\nEnded at r: %d , c: %d for %d\n\n",r,c,ed);
		return DP[mask][pos] = ed;
	}
	if (pos != start_pos){
		if (DP[mask][pos] != -1) {
			return DP[mask][pos];
		}
	}
	int dist = Max;
	//One by one trying to select next # to take
	for (int i = 0; i < total_nut; i++) {
		if (Check(mask, i) == 0) {
			//printf("Taking hash: %d where r: %d , c: %d\n",i,Map[i].first,Map[i].second);
			int total_cost = call(Set(mask, i), Map[i].first, Map[i].second, i)	+ distances[pos][i];
			//printf("...At this step, res: %d...\n",total_cost);
			dist = min(dist, total_cost);
		}
	}
	//printf("\nFinally at row: %d , col: %d mask: %d , cost: %d\n\n",r,c,mask,dist);
	if (dist != Max && pos != start_pos) {
		return DP[mask][pos] = dist;
	}
	return dist;
}

int main() {
	while (scanf("%d %d", &row, &col) == 2) {
		total_nut = 0;
		getchar();
		for(int i = 0;i<row;i++){
			gets(M[i]);
		}
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				if (M[i][j] == 'L') {
					sx = i;
					sy = j;
				}
				//Saving in Map where we find #
				if (M[i][j] == '#') {
					pair<int, int> P;
					P.first = i;
					P.second = j;
					Map[total_nut] = P;
					total_nut++;
				}
			}
		}
		calculate_path();
		memset(DP, -1, sizeof(DP));
		int res = call(0, sx, sy, start_pos);
		printf("%d\n", res);
	}
	return 0;
}
