一个n*m个grid上面有x个man和x个house,现在就是man每移动一步就需要花费1元,现在就是x个人要找房子呆着,且一个房子只能容纳一个人,求所有人找到呆着的房子的最小花费。
建立一个超级源点s和汇点t,s到每个人建立一条容量为1、费用为0的边,每个人到每个房子建立一条容量为inf、费用为两者间的最小距离,方向变的费用为负,房子到t建立一条容量为1、费用为0的边。。。
/*****************************************
Author :Crazy_AC(JamesQi)
Time :2015
File Name :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 110;
int cap[maxn*2][maxn*2], pre[maxn*2], cost[maxn*2][maxn*2];
vector<ii> men,house;
int s, t;
char str[maxn];
int n, m;
int num;
bool vis[maxn*2];
int dis[maxn*2];
bool spfa() {
queue<int> que;
memset(dis, INF,sizeof dis);
memset(vis, false,sizeof vis);
memset(pre, -1,sizeof pre);
dis[s] = 0,vis[s] = true;
que.push(s);
while(!que.empty()) {
int u = que.front();
que.pop();
vis[u] = false;
for (int v = s;v <= t;++v) {
if (cap[u][v] > 0 && dis[v] > dis[u] + cost[u][v]) {
dis[v] = dis[u] + cost[u][v];
pre[v] = u;
if (!vis[v]) {
vis[v] = true;
que.push(v);
}
}
}
}
return pre[t] != -1;
}
int MCMF() {
int ret = 0;
while(spfa()) {
for (int v = t;v != s;v = pre[v]) {
cap[pre[v]][v] -= 1;
cap[v][pre[v]] += 1;
}
ret += dis[t];
}
return ret;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(scanf("%d%d",&n,&m)) {
if (n==0&&m==0) break;
men.clear(),house.clear();
for (int i = 1;i <= n;++i) {
scanf("%s",str+1);
for (int j = 1;j <= m;++j) {
if (str[j] == 'H') house.push_back(ii(i, j));
if (str[j] == 'm') men.push_back(ii(i, j));
}
}
memset(cap, 0,sizeof cap);
memset(cost, 0,sizeof cost);
num = (int)men.size();
s = 0, t = num*2+1;
for (int i = 0;i < num;++i) {
int u = i + 1;
cap[s][u] = 1;
for (int j = 0;j < num;++j) {
int dis = abs(men[i].first - house[j].first) + abs(men[i].second - house[j].second);
int v = j + 1 + num;
cap[v][t] = 1;
cap[u][v] = INF;
cost[u][v] = dis;
cost[v][u] = -dis;
}
}
printf("%d\n", MCMF());
}
return 0;
}
/*****************************************
Author :Crazy_AC(JamesQi)
Time :2016
File Name :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 110;
struct Point{
int x,y;
Point(){}
Point(int x,int y):x(x),y(y){}
int operator - (const Point& rhs) {
return abs(x - rhs.x) + abs(y - rhs.y);
}
}A[maxn],B[maxn];
int cnt1,cnt2;
int n, m;
char str[maxn];
int head[maxn*2],cap[maxn*maxn*2],flow[maxn*maxn*2],nxt[maxn*maxn*2],cost[maxn*maxn*2],pnt[maxn*maxn*2];
int pre[maxn*2];
int ecnt;
int s, t;
inline void addedge(int u,int v,int c,int w) {
cap[ecnt] = c, flow[ecnt] = 0,cost[ecnt] = w,pnt[ecnt] = v;
nxt[ecnt] = head[u],head[u] = ecnt++;
cap[ecnt] = 0,flow[ecnt] = 0,cost[ecnt] = -w,pnt[ecnt] = u;
nxt[ecnt] = head[v],head[v] = ecnt++;
}
int dis[maxn*2];
bool vis[maxn*2];
bool spfa() {
queue<int> que;
memset(pre, -1,sizeof pre);
memset(dis, INF,sizeof dis);
memset(vis, false,sizeof vis);
que.push(s);
vis[s] = true;
dis[s] = 0;
while(!que.empty()) {
int u = que.front();
que.pop();
vis[u] = false;
for (int i = head[u];i != -1;i = nxt[i]) {
int v = pnt[i];
if (cap[i] > flow[i] && dis[v] > dis[u] + cost[i]) {
dis[v] = dis[u] + cost[i];
pre[v] = i;
if (!vis[v]) {
vis[v] = true;
que.push(v);
}
}
}
}
return dis[t] != INF;
}
int MCMF() {
int ret = 0;
while(spfa()) {
int minflow = INF;
for (int v = t;v != s;v = pnt[pre[v]^1]) {
int i = pre[v];
minflow = min(minflow, cap[i] - flow[i]);
}
ret += minflow * dis[t];
for (int v = t;v != s;v = pnt[pre[v]^1]) {
int i = pre[v];
flow[i] += minflow;
flow[i^1] -= minflow;
if (pre[v]==-1)break;
}
}
return ret;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(scanf("%d%d",&n,&m)) {
if (n==0&&m==0)break;
cnt1 = cnt2 = 0;
for (int i = 1;i <= n;++i) {
scanf("%s",str+1);
for (int j = 1;j <= m;++j) {
if (str[j] == 'H') A[++cnt1] = Point(i, j);
if (str[j] == 'm') B[++cnt2] = Point(i, j);
}
}
s = 0,t = 2*cnt1+1;
memset(head, -1,sizeof head);
ecnt = 0;
for (int i = 1;i <= cnt1;++i) {//cnt1 == cnt2;
addedge(s, i, 1, 0);
addedge(i+cnt1, t, 1, 0);
for (int j = 1;j <= cnt2;++j) {
int dis = A[i] - B[j];
addedge(i,j+cnt1,INF,dis);
}
}
printf("%d\n", MCMF());
}
return 0;
}