只需要在每个m和H之间进行连边,边权为曼哈顿距离。 然和可以采用二分图最大权匹配或者是费用流。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int MAX=310;
const int INF=1010101010;
struct mcmf
{
struct Edge
{
int to;
int cap;
int cost;
int next;
}edge[400000];
int st,ed;
int cnt,head[MAX];
int dist[MAX],vist[MAX],pre[MAX],pos[MAX];
void adde(int u,int v,int cap,int cost)
{
edge[cnt].to=v;
edge[cnt].cap=cap;
edge[cnt].cost=cost;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].to=u;
edge[cnt].cap=0;
edge[cnt].cost=-cost;
edge[cnt].next=head[v];
head[v]=cnt++;
}
void init()
{
memset(head,-1,sizeof(head));
cnt=0;
}
int solve()
{
int u,maxflow=0,mincost=0;
for(;;)
{
for(int i=st;i<=MAX;i++)
{
vist[i]=0;
pre[i]=-1;
dist[i]=INF;
}
dist[st]=0;
vist[st]=1;
pre[st]=st;
queue<int>q;
q.push(st);
while(!q.empty())
{
u=q.front();
q.pop();
vist[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>0&&dist[v]>dist[u]+edge[i].cost)
{
dist[v]=dist[u]+edge[i].cost;
pre[v]=u;
pos[v]=i;
if(!vist[v])
{
vist[v]=1;
q.push(v);
}
}
}
}
if(dist[ed]==INF)break;
maxflow++;
mincost+=dist[ed];
for(u=ed;u!=st;u=pre[u])
{
edge[pos[u]].cap--;
edge[pos[u]^1].cap++;
}
}
return mincost;
}
};
int n,m;
int h[1010][2];
int hh[1010][2];
char s[200][200];
mcmf mm;
int main()
{
while(cin>>n>>m&&(n+m))
{
mm.init();
mm.st=1;
mm.ed=2;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>s[i][j];
}
}
int hcnt=0,mcnt=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(s[i][j]=='H')
{
h[hcnt][0]=i;
h[hcnt][1]=j;
hcnt++;
}
if(s[i][j]=='m')
{
hh[mcnt][0]=i;
hh[mcnt][1]=j;
mcnt++;
}
}
}
for(int i=0;i<hcnt;i++)
{
mm.adde(1,3+i,1,0);
}
for(int i=0;i<mcnt;i++)
{
mm.adde(3+hcnt+i,2,1,0);
}
for(int i=0;i<hcnt;i++)
{
for(int j=0;j<mcnt;j++)
{
int dd=abs(h[i][0]-hh[j][0])+abs(h[i][1]-hh[j][1]);
mm.adde(3+i,3+hcnt+j,1,dd);
}
}
cout<<mm.solve()<<endl;
}
}