#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<vector> using namespace std; #define N 10000+10 #define INF 0x3f3f3f3f struct edge{ int from,to,cap,flow,cost; edge(int a,int b,int c,int d,int e){from=a,to=b,c=cap,d=flow,e=cost;} }; vector<edge>e;vector<int>g[N]; int row,col;char mp[101][101];int m_x[500],m_y[500],h_x[500],h_y[500];int cnt1=0,cnt2=0; void add_edge(int f,int to,int cap,int flow,int cost ){ e.push_back(edge(f,to,cap,0,cost)); e.push_back(edge(to,f,0,0,-cost)); int m=e.size(); g[f].push_back(m-2);//正向边 g[to].push_back(m-1);//反向边 } int dis[N],vis[N],res[N],pre[N]; bool spfa(int s,int t,int &flow,int &cost){ memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(res,0x3f,sizeof(res)); dis[s]=0;queue<int>q;q.push(s);vis[s]=1; while(!q.empty()){ int u=q.front();q.pop();vis[u]=0; for(int i=0;i<g[u].size();i++){ edge &v=e[g[u][i]]; if(v.cap>v.flow&&dis[v.to]>dis[u]+v.cost){ dis[v.to]=dis[u]+v.cost; pre[v.to]=g[u][i]; res[v.to]=min(res[u],v.cap-v.flow); if(!vis[v.to]) q.push(v.to),vis[v.to]=1; } } } if(dis[t]==INF) return false; flow+=res[t];cost+=dis[t]*res[t]; for(int u=t;u!=s;u=e[pre[u]].from){ e[pre[u]].flow+=res[t]; e[pre[u]^1].flow-=res[t]; } return true; } int mcmf(int s,int t,int &cost){ int flow=0;cost =0; while(spfa(s,t,flow,cost)); return flow; } int main(){ while(~scanf("%d%d",&row,&col),row+col){ for(int i=0;i<row;i++) scanf("%s",&mp[i]); for(int i=0;i<row;i++) for(int j=0;j<col;j++) { if(mp[i][j]=='m'){ add_edge(row*col+1,i*col+j,1,0,0); m_x[cnt1]=i,m_y[cnt1]=j;cnt1++; } else if(mp[i][j]=='H'){ add_edge(i*col+j,row*col+2,1,0,0); h_x[cnt2]=i,h_y[cnt2]=j;cnt2++; } } for(int i=0;i<cnt1;i++) for(int j=0;j<cnt2;j++){ add_edge((m_x[i]*col+m_y[j]),(h_x[i]*col+h_y[j]),1,0,abs(m_x[i]-h_x[i])+abs(m_y[i]-h_y[i])); } //cout<<cnt1<<' '<<cnt2<<endl; int cost=0; mcmf(row*col+1,row*col+2,cost); printf("%d\n",cost); } return 0; }