#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>/
// #include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define mp make_pair
#define PI ( acos(-1.0) )
#define IN freopen("nocross.in","r",stdin)
#define OUT freopen("nocross.out","w",stdout)
#define FOR(i,a,b) for(i=a ; i<=b ; i++)
#define DBG printf("Hi\n")
#define i64 long long int
#define eps (1e-8)
#define xx first
#define yy second
#define ln 17
#define off 2
#define SZ(z) ((int)z.size())

#define FastIO ios_base::sync_with_stdio(false); cin.tie(NULL)

// using namespace __gnu_pbds;
using namespace std ;

// typedef tree< i64, null_type, less<i64>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

//#define maxn 1000005
//#define INF 2000000000000000000LL
//#define mod 998244353LL

namespace mcmf
{
//this should be at least 2*( added edge in the graph )
const int MAX = 500000;
const long long INF = 1LL << 60;

long long cap[MAX], flow[MAX], cost[MAX], dis[MAX];
int n, m, s, t, Q[MAX*10], adj[MAX], link[MAX], last[MAX], from[MAX], visited[MAX];

void init(int nodes, int source, int sink)
{
    m = 0, n = nodes, s = source, t = sink;
    for (int i = 0; i <= n; i++) last[i] = -1;
}

void addEdge(int u, int v, long long c, long long w)
{
    adj[m] = v, cap[m] = c, flow[m] = 0, cost[m] = +w, link[m] = last[u], last[u] = m++;
    adj[m] = u, cap[m] = 0, flow[m] = 0, cost[m] = -w, link[m] = last[v], last[v] = m++;
}

bool spfa()
{
    int i, j, x, f = 0, l = 0;
    for (i = 0; i <= n; i++) visited[i] = 0, dis[i] = INF;

    dis[s] = 0, Q[l++] = s;
    while (f < l)
    {
        i = Q[f++];
        for (j = last[i]; j != -1; j = link[j])
        {
            if (flow[j] < cap[j])
            {
                x = adj[j];
                if (dis[x] > dis[i] + cost[j])
                {
                    dis[x] = dis[i] + cost[j], from[x] = j;
                    if (!visited[x])
                    {
                        visited[x] = 1;
                        if (f && rand() & 7) Q[--f] = x;
                        else Q[l++] = x;
                    }
                }
            }
        }
        visited[i] = 0;
    }
    return (dis[t] != INF);
}

pair <long long, long long> solve()
{
    int i, j;
    long long mincost = 0, maxflow = 0;

    while (spfa())
    {
        long long aug = INF;
        for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i])
        {
            aug = min(aug, cap[j] - flow[j]);
        }
        for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i])
        {
            flow[j] += aug, flow[j ^ 1] -= aug;
        }
        maxflow += aug, mincost += aug * dis[t];
    }
    return make_pair(mincost, maxflow);
}
}

int dp[55][55][55][55] ;
char s[55][55] ;
int cnt[55][55] ;

int main()
{
    int n , m ;
    scanf("%d %d",&n,&m) ;

    for(int i=0 ; i<n ; i++)
    {
        scanf("%s",s[i]) ;
    }

    for(int i=n-1 ; i>=0; i--)
    {
        for(int j=m-1 ; j>=0 ; j--)
        {
            if( s[i][j]=='#' ) continue ;
            dp[i][j][i][j] = 1 ;

            if( i< n-1 )
            {
                for(int k=0 ; k<n; k++)
                {
                    for(int l=0 ; l<m ; l++) dp[i][j][k][l] |= dp[i+1][j][k][l] ;
                }
            }
            if( j< m-1 )
            {
                for(int k=0 ; k<n; k++)
                {
                    for(int l=0 ; l<m ; l++) dp[i][j][k][l] |= dp[i][j+1][k][l] ;
                }
            }
        }
    }

    int cntob = 0 ;
    for(int i=0 ; i<n ; i++)
    {
        for(int j=0 ; j<m ; j++) if( s[i][j] == 'o' ) cnt[i][j] = cntob++ ;
    }

    int src = cntob + n*m  , sink = cntob + n*m+1 ;

    mcmf::init( cntob + n*m + 2 , src,sink ) ;

    for(int i=0 ; i<n ; i++)
    {
        for(int j=0 ; j<m ; j++)
        {
            if(s[i][j]!='o') continue ;

            for(int k=0 ; k<n ; k++)
            {
                for(int l=0 ; l<m ; l++)
                {
                    if( dp[i][j][k][l]  ) mcmf::addEdge( cnt[i][j] , cntob+ k*m + l , 1, -((k+l) - (i+j)) ) ;
                }
            }
        }
    }

    for(int i=0 ; i<n ; i++)
    {
        for(int j=0; j<m ; j++)
        {
            if( s[i][j]=='o' ) mcmf::addEdge(src , cnt[i][j],1,0) ;
            if( s[i][j] != '#' ) mcmf::addEdge( cntob+i*m+j , sink , 1 , 0 ) ;
        }
    }

    pair<int,int> ans = mcmf::solve() ;

    printf("%d\n",-ans.xx) ;

    return 0 ;
}


Measured memory_bytes: 37852