#include <bits/stdc++.h>

using namespace std;


template<typename T>
class maximum_flow{
public:
	class edge{
	public:
		int to,rev;
		T cap,ini;//if ini>0, flow on this edge is (ini-cap).
	};
	int n;
	vector<vector<edge>> ad;
	vector<int> level,itr;
	T inf;
	
	maximum_flow(int n){
		this->n=n;
		inf=numeric_limits<T>::max();
		ad.resize(n);
		level.resize(n);
		itr.resize(n);
		fill(level.begin(),level.end(),-1);
	}
	
	void add_edge(int from,int to,T cap){
		edge e0,e1;
		e0.to=to,e0.rev=ad[to].size(),e0.cap=cap,e0.ini=cap;
		e1.to=from,e1.rev=ad[from].size(),e1.cap=0,e1.ini=0;
		ad[from].push_back(e0);
		ad[to].push_back(e1);
	}
	
	void bfs(int s){
		fill(level.begin(),level.end(),-1);
		level[s]=0;
		queue<int> que;
		que.push(s);
		while(que.size()){
			int v=que.front();
			que.pop();
			for(int i=0;i<ad[v].size();i++){
				edge &e=ad[v][i];
				if(e.cap>0 && level[e.to]<0){
					level[e.to]=level[v]+1;
					que.push(e.to);
				}
			}
		}
	}
	
	T dfs(int v,int t,T f){
		if(v==t) return f;
		for(;itr[v]<ad[v].size();itr[v]++){
			edge &e=ad[v][itr[v]];
			if(e.cap>0 && level[v]<level[e.to]){
				T d=dfs(e.to,t,min(f,e.cap));
				if(d>0){
					e.cap-=d;
					ad[e.to][e.rev].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	
	T flow(int s,int t){//s and t must be fixed.
		T res=0,f=0;
		bfs(s);
		while(level[t]>=0){
        	fill(itr.begin(),itr.end(),0);
			f=dfs(s,t,inf);
			while(f>0){
				res+=f;
				f=dfs(s,t,inf);
			}
			bfs(s);
		}
		return res;
	}
};
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	
	int n,m;
	cin >> n >> m;
	vector<vector<bool>> ta(n,vector<bool>(m));
	vector<pair<int,int>> koma;
	for(int i=0;i<n;i++){
		string str;
		cin >> str;
		for(int j=0;j<m;j++){
			if(str[j]=='#'){
				ta[i][j]=true;
			}
			if(str[j]=='o'){
				koma.push_back(make_pair(i,j));
			}
		}
	}
	sort(koma.begin(),koma.end());
	reverse(koma.begin(),koma.end());
	
	long long res=0;
	int h=koma.size();
	int sum2=0;
	vector<vector<vector<bool>>> rea(h,vector<vector<bool>>(n,vector<bool>(m)));
	for(int i=0;i<(int)koma.size();i++){
		sum2+=koma[i].first+koma[i].second;
		vector<vector<bool>> ta2(n,vector<bool>(m));
		for(int ii=0;ii<n;ii++){
			for(int jj=0;jj<m;jj++){
				ta2[ii][jj]=ta[ii][jj];
			}
		}
		
		int vv=0;
		int vx=koma[i].first,vy=koma[i].second;
		function<void(int,int)> dfs=[&](int x,int y){
			ta2[x][y]=true;
			rea[i][x][y]=true;
			int nx=x+1,ny=y;
			if(nx<n && ny<m && (!ta2[nx][ny])){
				ta2[nx][ny]=true;
				dfs(nx,ny);
			}
			nx=x,ny=y+1;
			if(nx<n && ny<m && (!ta2[nx][ny])){
				ta2[nx][ny]=true;
				dfs(nx,ny);
			}
		};
		dfs(koma[i].first,koma[i].second);
	}
	
	int prev=0;
	vector<pair<int,int>> hens;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			hens.push_back(make_pair(i,j));
		}
	}
	sort(hens.begin(),hens.end(),[&](pair<int,int> p0,pair<int,int> p1){
		int v0=p0.first+p0.second;
		int v1=p1.first+p1.second;
		if(v0==v1) return p0.first<p1.first;
		return v0>v1;
	});
	
	vector<pair<int,int>> ris;
	
	long long sum=0;
	for(int i=0;i<(n*m);i++){
		if(ta[hens[i].first][hens[i].second]) continue;
		
		ris.push_back(hens[i]);
		sum+=hens[i].first+hens[i].second;
		
		int ri=(int)ris.size();
		int le=h;
		maximum_flow<int> mf(ri+le+2);
		for(int j=0;j<h;j++){
			for(int k=0;k<ri;k++){
				if(!rea[j][ris[k].first][ris[k].second]) continue;
				mf.add_edge(j+1,1+h+k,1);
			}
		}
		for(int j=0;j<h;j++) mf.add_edge(0,j+1,1);
		for(int j=0;j<ri;j++) mf.add_edge(j+1+h,ri+le+1,1);
		
		int fl=mf.flow(0,ri+le+1);
		if(fl==prev){
			sum-=hens[i].first+hens[i].second;
			ris.pop_back();
		}else{
			if(fl==le){
				cout << sum-sum2 << "\n";
				break;
			}
		}
		prev=fl;
	}
	return 0;
}

Measured memory_bytes: 4268