/* 二分图 最小权匹配问题,题目给定条件可以看出是完备匹配; 利用最小费用最大流解决 X集合连源点,边权为1,花费0 Y集合连汇点,边权为1,花费0 X连Y中任意元素,边权为1,花费为两者曼哈顿距离 最后得到的最小费用就是最小权匹配 */ #include <stdio.h> #include <iostream> #include <string.h> #include<queue> #include<cmath> using namespace std; const int M=20010,ME=100000; const int INF=0x3f3fffff; struct point { int x,y; point(){} point(const int _x,const int _y){x=_x,y=_y;} }p1[51*51], p2[51*51]; //****************************** int Head[M],Next[ME],Num[ME],Flow[ME],Cap[ME],Cost[ME],Q[M],InQ[M],Len[M],pre_edge[M]; class MaxFlow { public: void clear() { memset(Head,-1,sizeof(Head)); memset(Flow,0,sizeof(Flow)); } void addedge(int u,int v,int cap,int cost) { Next[top] = Head[u]; Num[top] = v; Cap[top] = cap; Cost[top] = cost; Head[u] = top++; Next[top] = Head[v]; Num[top] = u; Cap[top] = 0; Cost[top] = -cost; Head[v] = top++; } int solve(int s,int t) //返回最终的cost { int cost = 0; while(SPFA(s,t)) { int cur = t,minflow = INF; while(cur != s) { if(minflow > Cap[pre_edge[cur]]-Flow[pre_edge[cur]]) minflow = Cap[pre_edge[cur]]-Flow[pre_edge[cur]]; cur = Num[pre_edge[cur] ^ 1]; } cur = t ; while(cur != s) { Flow[pre_edge[cur]] += minflow; Flow[pre_edge[cur] ^ 1] -= minflow; cost += minflow * Cost[pre_edge[cur]]; cur = Num[pre_edge[cur] ^ 1]; } } return cost; } private: bool SPFA(int s,int t) { fill(Len,Len+M,INF); Len[s]=0; int head = -1,tail = -1,cur; Q[++head] = s; while(head != tail) { ++tail; if(tail >= M) tail = 0 ; cur = Q[tail]; for(int i = Head[cur];i != -1;i = Next[i]) { if(Cap[i]>Flow[i] && Len[Num[i]] > Len[cur] + Cost[i]) { Len[Num[i]] = Len[cur] + Cost[i]; pre_edge[Num[i]] = i; if(!InQ[Num[i]]) { InQ[Num[i]]=true; ++head; if(head >= M) head = 0; Q[head] = Num[i]; } } } InQ[cur]=false; } return Len[t] != INF; } int top; }my; //****************************** int n,m; char graph[109][109]; int main() { while(scanf("%d%d",&n,&m),n+m) { my.clear(); for(int i=0;i<n;i++) scanf("%s",graph[i]); int num1=1,num2=1; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(graph[i][j]=='H') p2[num2++]=point(i,j); if(graph[i][j]=='m') p1[num1++]=point(i,j); } } for(int i=1;i<num1;i++) { for(int j=1;j<num2;j++) { int cost=fabs(p1[i].x-p2[j].x)+fabs(p1[i].y-p2[j].y); my.addedge(i,j+num1,1,cost); } } int S=0,T=num1+num2; for(int i=1;i<num1;i++) my.addedge(S,i,1,0); for(int j=1;j<num2;j++) my.addedge(j+num1,T,1,0); printf("%d\n",my.solve(S,T)); } return 0; }