Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3961 Accepted Submission(s): 2036
2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0
2 10 28
#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
const int MAXN=110;
const int inf=1<<30;
using namespace std;
char G[MAXN][MAXN];
int map[MAXN][MAXN];
int lx[MAXN],ly[MAXN];
int match[MAXN];
bool visitx[MAXN],visity[MAXN];
int n;
int Hungary(int u){
visitx[u]=true;
for(int i=0;i<n;i++){
if(!visity[i]&&lx[u]+ly[i]==map[u][i]){
visity[i]=true;
if(match[i]==-1||Hungary(match[i])){
match[i]=u;
return true;
}
}
}
return false;
}
void KM_prefect_match(){
int tmp;
//注意,此时要初始化为无穷小
for(int i=0;i<n;i++){
lx[i]=-inf;
}
memset(ly,0,sizeof(ly));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
lx[i]=max(lx[i],map[i][j]);
}
}
for(int i=0;i<n;i++)
{
while(1){
memset(visitx,false,sizeof(visitx));
memset(visity,false,sizeof(visity));
if(Hungary(i))//匹配成功
break;
else {
tmp=inf;
for(int j=0;j<n;j++)if(visitx[j]){//x在交错树中
for(int k=0;k<n;k++){
//y在交错树外
if(!visity[k]&&tmp>lx[j]+ly[k]-map[j][k]){
tmp=lx[j]+ly[k]-map[j][k];
}
}
}
//更新顶标
for(int j=0;j<n;j++){
if(visitx[j])
lx[j]-=tmp;
if(visity[j])
ly[j]+=tmp;
}
}
}
}
}
int main(){
int row,col;
while(~scanf("%d%d",&row,&col)){
if(row==0&&col==0)break;
n=0;
int cnt1=0,cnt2=0;
memset(map,0,sizeof(map));
memset(match,-1,sizeof(match));
for(int i=0;i<row;i++){
scanf("%s",G[i]);
for(int j=0;j<col;j++){
if(G[i][j]=='m')n++;
}
}
//建图很重要!!!
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(G[i][j]=='m'){
for(int k=0;k<row;k++){
for(int l=0;l<col;l++){
if(G[k][l]=='H'){
map[cnt1][cnt2++]=-1*(abs(i-k)+abs(j-l));//由于求得是最小权值和,取相反数
}
}
}
cnt1++;
cnt2=0;
}
}
}
KM_prefect_match();
int ans=0;
for(int i=0;i<n;i++){
ans+=map[match[i]][i];
}
printf("%d\n",-ans);//最后取相反数就行了
}
return 0;
}