/*
* @Author: hungeazy
* @Date: 2025-10-28 13:46:40
* @Last Modified by: hungeazy
* @Last Modified time: 2025-10-28 15:20:29
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt")
using namespace std;
using namespace __gnu_pbds;
bool M1;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define ll long long
#define ull unsigned long long
#define sz(x) x.size()
#define sqr(x) (1LL * (x) * (x))
#define all(x) x.begin(), x.end()
#define fill(f,x) memset(f,x,sizeof(f))
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define FOD(i,r,l) for(int i=r;i>=l;i--)
#define debug(x) cout << #x << " = " << x << '\n'
#define ii pair<int,int>
#define iii pair<int,ii>
#define di pair<ii,ii>
#define vi vector<int>
#define vii vector<ii>
#define mii map<int,int>
#define fi first
#define se second
#define pb push_back
#define MOD 1000000007
#define __lcm(a,b) (1ll * ((a) / __gcd((a), (b))) * (b))
#define YES cout << "YES\n"
#define NO cout << "NO\n"
#define MASK(i) (1LL << (i))
#define c_bit(i) __builtin_popcountll(i)
#define BIT(x,i) ((x) & MASK(i))
#define SET_ON(x,i) ((x) | MASK(i))
#define SET_OFF(x,i) ((x) & ~MASK(i))
#define oo 1e18
#define name "ISLAND"
#define endl '\n'
#define memory() cerr << abs(&M2-&M1)/1024.0/1024 << " MB" << endl
#define time() cerr << endl << "-------------Time:" << 1000.0 * clock() / CLOCKS_PER_SEC << "ms." << endl
template<typename T> bool maximize(T &res, const T &val) { if (res < val){ res = val; return true; }; return false; }
template<typename T> bool minimize(T &res, const T &val) { if (res > val){ res = val; return true; }; return false; }
template <class T> using ordered_set = tree <T, null_type, less_equal <T>, rb_tree_tag,tree_order_statistics_node_update>;
const int N = 60;
int r,c;
char a[N][N];
int dx[] = {1,0,-1,0},
dy[] = {0,1,0,-1};
namespace hungeazy {
int d[20][20],dist[N][N],pos[N][N],dp[16][MASK(16)],len;
bool ok[N][N],visited[N][N];
vii vec;
bool check(int x, int y) {
return (x >= 1 and x <= r and y >= 1 and y <= c);
}
void BFS(int p)
{
FOR(i,0,len-1) d[p][i] = oo;
FOR(i,1,r)
FOR(j,1,c)
{
visited[i][j] = false;
dist[i][j] = oo;
}
d[p][p] = 0;
dist[vec[p].fi][vec[p].se] = 0;
visited[vec[p].fi][vec[p].se] = true;
deque<pair<int,ii>> q;
q.pb({p,vec[p]});
while (!q.empty())
{
int cur = q.front().fi;
auto [u,v] = q.front().se;
q.pop_front();
FOR(s,0,3)
{
int x = dx[s]+u, y = dy[s]+v, newCur = cur;
if (!check(x,y) or a[x][y] == '.') continue;
if (a[x][y] == 'S')
{
if (minimize(dist[x][y],dist[u][v]+1) and !visited[x][y])
{
visited[x][y] = true;
q.pb({cur,{x,y}});
}
}
else
{
if (minimize(dist[x][y],dist[u][v]) and !visited[x][y])
{
if (ok[x][y])
{
int vt = pos[x][y];
minimize(d[p][vt],d[p][cur]+dist[x][y]);
newCur = vt;
}
visited[x][y] = true;
q.push_front({newCur,{x,y}});
}
}
}
}
}
void solve(void)
{
FOR(i,1,r)
FOR(j,1,c)
if (a[i][j] == 'X')
{
vec.pb({i,j});
ok[i][j] = true;
}
if (vec.empty())
{
cout << 0;
return;
}
len = sz(vec);
FOR(i,0,len-1) pos[vec[i].fi][vec[i].se] = i;
FOR(i,0,len-1) BFS(i);
fill(dp,0x3f);
int INF = dp[0][0];
FOR(i,0,len-1) dp[i][MASK(i)] = 0;
FOR(mask,1,MASK(len)-1)
FOR(i,0,len-1)
if (BIT(mask,i) and dp[i][mask] != INF)
{
FOR(j,0,len-1)
if (!BIT(mask,j))
minimize(dp[j][SET_ON(mask,j)],dp[i][mask]+d[i][j]);
}
int ans = oo;
FOR(i,0,len-1) minimize(ans,dp[i][MASK(len)-1]);
cout << ans;
}
}
bool M2;
signed main()
{
fast;
if (fopen(name".inp","r"))
{
freopen(name".inp","r",stdin);
freopen(name".out","w",stdout);
}
cin >> r >> c;
FOR(i,1,r)
FOR(j,1,c) cin >> a[i][j];
hungeazy::solve();
time();
memory();
return 0;
}
// ██░ ██ █ ██ ███▄ █ ▄████
//▓██░ ██▒ ██ ▓██▒ ██ ▀█ █ ██▒ ▀█▒
//▒██▀▀██░▓██ ▒██░▓██ ▀█ ██▒▒██░▄▄▄░
//░▓█ ░██ ▓▓█ ░██░▓██▒ ▐▌██▒░▓█ ██▓
//░▓█▒░██▓▒▒█████▓ ▒██░ ▓██░░▒▓███▀▒
// ▒ ░░▒░▒░▒▓▒ ▒ ▒ ░ ▒░ ▒ ▒ ░▒ ▒
// ▒ ░▒░ ░░░▒░ ░ ░ ░ ░░ ░ ▒░ ░ ░
// ░ ░░ ░ ░░░ ░ ░ ░ ░ ░ ░ ░ ░
// ░ ░ ░ ░ ░ ░
LyoKKiBAQXV0aG9yOiBodW5nZWF6eQoqIEBEYXRlOiAgIDIwMjUtMTAtMjggMTM6NDY6NDAKKiBATGFzdCBNb2RpZmllZCBieTogICBodW5nZWF6eQoqIEBMYXN0IE1vZGlmaWVkIHRpbWU6IDIwMjUtMTAtMjggMTU6MjA6MjkKKi8KI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CiNpbmNsdWRlIDxleHQvcGJfZHMvYXNzb2NfY29udGFpbmVyLmhwcD4gCiNpbmNsdWRlIDxleHQvcGJfZHMvdHJlZV9wb2xpY3kuaHBwPiAKLy8gI3ByYWdtYSBHQ0Mgb3B0aW1pemUoIk8zIikgIAovLyAjcHJhZ21hIEdDQyBvcHRpbWl6ZSgidW5yb2xsLWxvb3BzIikgIAovLyAjcHJhZ21hIEdDQyB0YXJnZXQoImF2eDIsYm1pLGJtaTIscG9wY250LGx6Y250IikgIAp1c2luZyBuYW1lc3BhY2Ugc3RkOwp1c2luZyBuYW1lc3BhY2UgX19nbnVfcGJkczsgCmJvb2wgTTE7CiNkZWZpbmUgZmFzdCBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTsgY2luLnRpZShOVUxMKTsgY291dC50aWUoTlVMTCk7CiNkZWZpbmUgaW50IGxvbmcgbG9uZwojZGVmaW5lIGxsIGxvbmcgbG9uZyAKI2RlZmluZSB1bGwgdW5zaWduZWQgbG9uZyBsb25nCiNkZWZpbmUgc3ooeCkgeC5zaXplKCkKI2RlZmluZSBzcXIoeCkgKDFMTCAqICh4KSAqICh4KSkKI2RlZmluZSBhbGwoeCkgeC5iZWdpbigpLCB4LmVuZCgpCiNkZWZpbmUgZmlsbChmLHgpIG1lbXNldChmLHgsc2l6ZW9mKGYpKQojZGVmaW5lIEZPUihpLGwscikgZm9yKGludCBpPWw7aTw9cjtpKyspCiNkZWZpbmUgRk9EKGkscixsKSBmb3IoaW50IGk9cjtpPj1sO2ktLSkKI2RlZmluZSBkZWJ1Zyh4KSBjb3V0IDw8ICN4IDw8ICIgPSAiIDw8IHggPDwgJ1xuJwojZGVmaW5lIGlpIHBhaXI8aW50LGludD4KI2RlZmluZSBpaWkgcGFpcjxpbnQsaWk+CiNkZWZpbmUgZGkgcGFpcjxpaSxpaT4KI2RlZmluZSB2aSB2ZWN0b3I8aW50PgojZGVmaW5lIHZpaSB2ZWN0b3I8aWk+CiNkZWZpbmUgbWlpIG1hcDxpbnQsaW50PgojZGVmaW5lIGZpIGZpcnN0CiNkZWZpbmUgc2Ugc2Vjb25kCiNkZWZpbmUgcGIgcHVzaF9iYWNrCiNkZWZpbmUgTU9EIDEwMDAwMDAwMDcKI2RlZmluZSBfX2xjbShhLGIpICgxbGwgKiAoKGEpIC8gX19nY2QoKGEpLCAoYikpKSAqIChiKSkKI2RlZmluZSBZRVMgY291dCA8PCAiWUVTXG4iCiNkZWZpbmUgTk8gY291dCA8PCAiTk9cbiIKI2RlZmluZSBNQVNLKGkpICgxTEwgPDwgKGkpKQojZGVmaW5lIGNfYml0KGkpIF9fYnVpbHRpbl9wb3Bjb3VudGxsKGkpCiNkZWZpbmUgQklUKHgsaSkgKCh4KSAmIE1BU0soaSkpCiNkZWZpbmUgU0VUX09OKHgsaSkgKCh4KSB8IE1BU0soaSkpCiNkZWZpbmUgU0VUX09GRih4LGkpICgoeCkgJiB+TUFTSyhpKSkKI2RlZmluZSBvbyAxZTE4CiNkZWZpbmUgbmFtZSAiSVNMQU5EIgojZGVmaW5lIGVuZGwgJ1xuJwojZGVmaW5lIG1lbW9yeSgpIGNlcnIgPDwgYWJzKCZNMi0mTTEpLzEwMjQuMC8xMDI0IDw8ICIgTUIiIDw8IGVuZGwKI2RlZmluZSB0aW1lKCkgY2VyciA8PCBlbmRsIDw8ICItLS0tLS0tLS0tLS0tVGltZToiIDw8IDEwMDAuMCAqIGNsb2NrKCkgLyBDTE9DS1NfUEVSX1NFQyA8PCAibXMuIiA8PCBlbmRsCnRlbXBsYXRlPHR5cGVuYW1lIFQ+IGJvb2wgbWF4aW1pemUoVCAmcmVzLCBjb25zdCBUICZ2YWwpIHsgaWYgKHJlcyA8IHZhbCl7IHJlcyA9IHZhbDsgcmV0dXJuIHRydWU7IH07IHJldHVybiBmYWxzZTsgfQp0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBib29sIG1pbmltaXplKFQgJnJlcywgY29uc3QgVCAmdmFsKSB7IGlmIChyZXMgPiB2YWwpeyByZXMgPSB2YWw7IHJldHVybiB0cnVlOyB9OyByZXR1cm4gZmFsc2U7IH0KdGVtcGxhdGUgPGNsYXNzIFQ+IHVzaW5nIG9yZGVyZWRfc2V0ID0gdHJlZSA8VCwgbnVsbF90eXBlLCBsZXNzX2VxdWFsIDxUPiwgcmJfdHJlZV90YWcsdHJlZV9vcmRlcl9zdGF0aXN0aWNzX25vZGVfdXBkYXRlPjsKY29uc3QgaW50IE4gPSA2MDsKaW50IHIsYzsKY2hhciBhW05dW05dOwppbnQgZHhbXSA9IHsxLDAsLTEsMH0sCglkeVtdID0gezAsMSwwLC0xfTsKCm5hbWVzcGFjZSBodW5nZWF6eSB7CgoJaW50IGRbMjBdWzIwXSxkaXN0W05dW05dLHBvc1tOXVtOXSxkcFsxNl1bTUFTSygxNildLGxlbjsKCWJvb2wgb2tbTl1bTl0sdmlzaXRlZFtOXVtOXTsKCXZpaSB2ZWM7CgoJYm9vbCBjaGVjayhpbnQgeCwgaW50IHkpICB7CgkJcmV0dXJuICh4ID49IDEgYW5kIHggPD0gciBhbmQgeSA+PSAxIGFuZCB5IDw9IGMpOwoJfQoKCXZvaWQgQkZTKGludCBwKQoJewoJCUZPUihpLDAsbGVuLTEpIGRbcF1baV0gPSBvbzsKCQlGT1IoaSwxLHIpCgkJCUZPUihqLDEsYykgCgkJCXsKCQkJCXZpc2l0ZWRbaV1bal0gPSBmYWxzZTsKCQkJCWRpc3RbaV1bal0gPSBvbzsKCQkJfQoJCWRbcF1bcF0gPSAwOwoJCWRpc3RbdmVjW3BdLmZpXVt2ZWNbcF0uc2VdID0gMDsKCQl2aXNpdGVkW3ZlY1twXS5maV1bdmVjW3BdLnNlXSA9IHRydWU7CgkJZGVxdWU8cGFpcjxpbnQsaWk+PiBxOwoJCXEucGIoe3AsdmVjW3BdfSk7CgkJd2hpbGUgKCFxLmVtcHR5KCkpCgkJewoJCQlpbnQgY3VyID0gcS5mcm9udCgpLmZpOwoJCQlhdXRvIFt1LHZdID0gcS5mcm9udCgpLnNlOwoJCQlxLnBvcF9mcm9udCgpOwoJCQlGT1IocywwLDMpCgkJCXsKCQkJCWludCB4ID0gZHhbc10rdSwgeSA9IGR5W3NdK3YsIG5ld0N1ciA9IGN1cjsKCQkJCWlmICghY2hlY2soeCx5KSBvciBhW3hdW3ldID09ICcuJykgY29udGludWU7CgkJCQlpZiAoYVt4XVt5XSA9PSAnUycpCgkJCQl7CgkJCQkJaWYgKG1pbmltaXplKGRpc3RbeF1beV0sZGlzdFt1XVt2XSsxKSBhbmQgIXZpc2l0ZWRbeF1beV0pCQoJCQkJCXsKCQkJCQkJdmlzaXRlZFt4XVt5XSA9IHRydWU7CgkJCQkJCXEucGIoe2N1cix7eCx5fX0pOwoJCQkJCX0KCQkJCX0KCQkJCWVsc2UgIAoJCQkJewoJCQkJCWlmIChtaW5pbWl6ZShkaXN0W3hdW3ldLGRpc3RbdV1bdl0pIGFuZCAhdmlzaXRlZFt4XVt5XSkKCQkJCQl7CgkJCQkJCWlmIChva1t4XVt5XSkgCgkJCQkJCXsKCQkJCQkJCWludCB2dCA9IHBvc1t4XVt5XTsKCQkJCQkJCW1pbmltaXplKGRbcF1bdnRdLGRbcF1bY3VyXStkaXN0W3hdW3ldKTsKCQkJCQkJCW5ld0N1ciA9IHZ0OwoJCQkJCQl9CgkJCQkJCXZpc2l0ZWRbeF1beV0gPSB0cnVlOwoJCQkJCQlxLnB1c2hfZnJvbnQoe25ld0N1cix7eCx5fX0pOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCX0KCgl2b2lkIHNvbHZlKHZvaWQpCgl7CQoJCUZPUihpLDEscikKCQkJRk9SKGosMSxjKQkKCQkJCWlmIChhW2ldW2pdID09ICdYJykgCgkJCQl7CgkJCQkJdmVjLnBiKHtpLGp9KTsKCQkJCQlva1tpXVtqXSA9IHRydWU7CgkJCQl9CgkJaWYgKHZlYy5lbXB0eSgpKQoJCXsKCQkJY291dCA8PCAwOwoJCQlyZXR1cm47CgkJfQoJCWxlbiA9IHN6KHZlYyk7CgkJRk9SKGksMCxsZW4tMSkgcG9zW3ZlY1tpXS5maV1bdmVjW2ldLnNlXSA9IGk7CgkJRk9SKGksMCxsZW4tMSkgQkZTKGkpOwoJCWZpbGwoZHAsMHgzZik7CgkJaW50IElORiA9IGRwWzBdWzBdOwoJCUZPUihpLDAsbGVuLTEpIGRwW2ldW01BU0soaSldID0gMDsKCQlGT1IobWFzaywxLE1BU0sobGVuKS0xKQoJCQlGT1IoaSwwLGxlbi0xKQoJCQkJaWYgKEJJVChtYXNrLGkpIGFuZCBkcFtpXVttYXNrXSAhPSBJTkYpCgkJCQl7CgkJCQkJRk9SKGosMCxsZW4tMSkKCQkJCQkJaWYgKCFCSVQobWFzayxqKSkKCQkJCQkJCW1pbmltaXplKGRwW2pdW1NFVF9PTihtYXNrLGopXSxkcFtpXVttYXNrXStkW2ldW2pdKTsKCQkJCX0gCgkJaW50IGFucyA9IG9vOwoJCUZPUihpLDAsbGVuLTEpIG1pbmltaXplKGFucyxkcFtpXVtNQVNLKGxlbiktMV0pOwoJCWNvdXQgPDwgYW5zOwoJfQoJCn0KCmJvb2wgTTI7CnNpZ25lZCBtYWluKCkKewogICAgZmFzdDsKICAgIGlmIChmb3BlbihuYW1lIi5pbnAiLCJyIikpCiAgICB7CiAgICAJZnJlb3BlbihuYW1lIi5pbnAiLCJyIixzdGRpbik7CiAgICAJZnJlb3BlbihuYW1lIi5vdXQiLCJ3IixzdGRvdXQpOwogICAgfQogICAgY2luID4+IHIgPj4gYzsKICAgIEZPUihpLDEscikKICAgIAlGT1IoaiwxLGMpIGNpbiA+PiBhW2ldW2pdOwogICAgaHVuZ2Vhenk6OnNvbHZlKCk7CiAgICB0aW1lKCk7CiAgICBtZW1vcnkoKTsKICAgIHJldHVybiAwOwp9Ci8vIOKWiOKWiOKWkSDilojiloggIOKWiCAgICDilojiloggIOKWiOKWiOKWiOKWhCAgICDiloggICDiloTilojilojilojilogKLy/ilpPilojilojilpEg4paI4paI4paSIOKWiOKWiCAg4paT4paI4paI4paSIOKWiOKWiCDiloDiloggICDiloggIOKWiOKWiOKWkiDiloDilojilpIKLy/ilpLilojilojiloDiloDilojilojilpHilpPilojiloggIOKWkuKWiOKWiOKWkeKWk+KWiOKWiCAg4paA4paIIOKWiOKWiOKWkuKWkuKWiOKWiOKWkeKWhOKWhOKWhOKWkQovL+KWkeKWk+KWiCDilpHilojilogg4paT4paT4paIICDilpHilojilojilpHilpPilojilojilpIgIOKWkOKWjOKWiOKWiOKWkuKWkeKWk+KWiCAg4paI4paI4paTCi8v4paR4paT4paI4paS4paR4paI4paI4paT4paS4paS4paI4paI4paI4paI4paI4paTIOKWkuKWiOKWiOKWkSAgIOKWk+KWiOKWiOKWkeKWkeKWkuKWk+KWiOKWiOKWiOKWgOKWkgovLyDilpIg4paR4paR4paS4paR4paS4paR4paS4paT4paSIOKWkiDilpIg4paRIOKWkuKWkSAgIOKWkiDilpIgIOKWkeKWkiAgIOKWkgovLyDilpIg4paR4paS4paRIOKWkeKWkeKWkeKWkuKWkSDilpEg4paRIOKWkSDilpHilpEgICDilpEg4paS4paRICDilpEgICDilpEKLy8g4paRICDilpHilpEg4paRIOKWkeKWkeKWkSDilpEg4paRICAgIOKWkSAgIOKWkSDilpEg4paRIOKWkSAgIOKWkQovLyDilpEgIOKWkSAg4paRICAg4paRICAgICAgICAgICAgICDilpEgICAgICAg4paR