1 #include <cstdio>
2 #include <cstring>
3 #include <queue>
4 #include <vector>
5 #include <algorithm>
6 using namespace std;
7 #define N 205
8 #define INF 0x3f3f3f3f
9 struct node {
10 int x, y;
11 node () {}
12 node (int x, int y) : x(x), y(y) {}
13 };
14 struct Edge {
15 int cap, u, v, cost;
16 Edge() {}
17 Edge(int u, int v, int cap, int cost) : u(u), v(v), cap(cap), cost(cost) {}
18 }edge[N*N];
19 vector<node> p, h;
20 vector<int> G[N];
21 int tot, dis[N], inq[N], pre[N], S, T;
22
23 void AddEdge(int u, int v, int cap, int cost) {
24 edge[tot] = Edge(u, v, cap, cost);
25 G[u].push_back(tot++);
26 edge[tot] = Edge(v, u, 0, -cost);
27 G[v].push_back(tot++);
28 }
29
30 int CalDis(int x1, int y1, int x2, int y2) {
31 return abs(x1 - x2) + abs(y1 - y2);
32 }
33
34 bool SPFA() {
35 memset(inq, 0, sizeof(inq));
36 memset(dis, INF, sizeof(dis));
37 queue<int> que; que.push(S);
38 dis[S] = 0; inq[S] = 1;
39 while(!que.empty()) {
40 int u = que.front(); que.pop(); inq[u] = 0;
41 for(int i = 0; i < G[u].size(); i++) {
42 Edge &e = edge[G[u][i]];
43 if(e.cap > 0 && dis[e.v] > e.cost + dis[u]) {
44 // 当可以增广并且费用更小的时候
45 dis[e.v] = e.cost + dis[u];
46 pre[e.v] = G[u][i]; // 记录路径
47 if(inq[e.v]) continue;
48 que.push(e.v); inq[e.v] = 1;
49 }
50 }
51 }
52 return dis[T] < INF;
53 }
54
55 void MFMC(int &mincost, int &maxflow) {
56 int ans = 0, flow = INF, p;
57 // 从汇点沿着此次增广的路径往回走,当找到源点的时候退出
58 for(int u = T; u; u = edge[p].u) {
59 p = pre[u]; // 找增广的流量
60 if(edge[p].cap < flow) flow = edge[p].cap;
61 }
62 for(int u = T; u; u = edge[p].u) {
63 p = pre[u];
64 edge[p].cap -= flow; // 更新每条边的流量
65 edge[p^1].cap += flow;
66 ans += flow * edge[p].cost; // 费用 = 单位费用 * 流量
67 }
68 mincost += ans, maxflow += flow;
69 }
70
71
72 int main() {
73 int n, m;
74 char s[105];
75 while(scanf("%d%d", &n, &m), n + m) {
76 p.clear(); h.clear();
77 for(int i = 0; i < n; i++) {
78 scanf("%s", s);
79 for(int j = 0; j < m; j++) {
80 if(s[j] == 'H') h.push_back(node(i, j));
81 if(s[j] == 'm') p.push_back(node(i, j));
82 }
83 }
84 tot = 0; int sz1 = p.size(), sz2 = h.size();
85 S = 0, T = sz1 + sz2 + 1;
86 for(int i = 0; i <= T; i++) G[i].clear();
87 for(int i = 0; i < sz1; i++) // S到man
88 AddEdge(S, i + 1, 1, 0);
89 for(int i = 0; i < sz2; i++) // house到T
90 AddEdge(i + 1 + sz1, T, 1, 0);
91 for(int i = 0; i < sz1; i++) {
92 for(int j = 0; j < sz2; j++) {
93 int c = CalDis(p[i].x, p[i].y, h[j].x, h[j].y);
94 AddEdge(i + 1, j + 1 + sz1, 1, c);
95 }
96 }
97
98 int mincost = 0, maxflow = 0;
99 while(SPFA()) MFMC(mincost, maxflow);
100 printf("%d\n", mincost);
101 }
102 return 0;
103 }