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

using namespace __gnu_pbds;
using namespace std;

using ll = long long;
using ld = long double;

#define mp make_pair

typedef tree<
        pair<int, int>,
        null_type,
        less<pair<int, int>>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;


int p = 1000000007;


int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}


mt19937 rnd(time(0));

/*
const int N = 1200000;

vector<int> facs(N), invfacs(N);

void init()
{
    facs[0] = 1;
    for (int i = 1; i<N; i++) facs[i] = mul(facs[i-1], i);
    invfacs[N-1] = inv(facs[N-1]);
    for (int i = N-2; i>=0; i--) invfacs[i] = mul(invfacs[i+1], i+1);
}

int C(int n, int k)
{
    if (n<k) return 0;
    if (n<0 || k<0) return 0;
    return mul(facs[n], mul(invfacs[k], invfacs[n-k]));
}*/

pair<int, vector<int>> min_weight_perfect_matching(const vector<vector<int>> &a) {
    int n = a.size();
    int m = a[0].size();
    vector<int> u(n);
    vector<int> v(m);
    vector<int> p(m);
    vector<int> way(m);
    for (int i = 1; i < n; ++i) {
        vector<int> minv(m, numeric_limits<int>::max());
        vector<bool> used(m);
        p[0] = i;
        int j0 = 0;
        while (p[j0] != 0) {
            used[j0] = true;
            int i0 = p[j0];
            int delta = numeric_limits<int>::max();
            int j1 = 0;
            for (int j = 1; j < m; ++j)
                if (!used[j]) {
                    int d = a[i0][j] - u[i0] - v[j];
                    if (minv[j] > d) {
                        minv[j] = d;
                        way[j] = j0;
                    }
                    if (delta > minv[j]) {
                        delta = minv[j];
                        j1 = j;
                    }
                }
            for (int j = 0; j < m; ++j)
                if (used[j]) {
                    u[p[j]] += delta;
                    v[j] -= delta;
                } else
                    minv[j] -= delta;
            j0 = j1;
        }
        while (j0 != 0) {
            int j1 = way[j0];
            p[j0] = p[j1];
            j0 = j1;
        }
    }
    vector<int> matching(n);
    for (int i = 1; i < m; ++i)
        matching[p[i]] = i;
    return {-v[0], matching};
}


const int INF = 1e5;

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);

    int n, m;
    cin>>n>>m;
    vector<string> s(n);
    for (int i = 0; i<n; i++) cin>>s[i];

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

    vector<vector<int>> a;

    vector<int> zeros(n*m+1);
    a.push_back(zeros);

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

            vector<vector<bool>> d(n, vector<bool>(m, false));
            d[i][j] = true;
            vector<int> vals = {0};
            for (int x = 0; x<n; x++)
                for (int y = 0; y<m; y++)
                {
                    if (s[x][y]!='#')
                    {
                        if (x>0 && d[x-1][y]) d[x][y] = true;
                        if (y>0 && d[x][y-1]) d[x][y] = true;
                    }
                    if (!d[x][y]) vals.push_back(INF);
                    else vals.push_back(100 + i + j - x - y);
                }
            a.push_back(vals);
        }

    /*for (auto vec: a)
    {
        for (auto x: vec) cout<<x<<' ';
        cout<<endl;
    }*/

    auto [cost, matching] = min_weight_perfect_matching(a);

    //cout<<cost<<endl;

    cout<<100*cnt-cost;

}



Measured memory_bytes: 4412