Description
Input
Output
Sample Input
2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0
Sample Output
2 10 28
Source
#include<queue> #include<cstdio> #include<string> #include<iostream> #include<algorithm> using namespace std; const int maxn=105; const int inf=0x3f3f3f3f; char str[maxn][maxn]; bool visx[maxn],visy[maxn];//在增广路中的点 int mark[maxn]; int lx[maxn],ly[maxn]; int slack[maxn]; int nx,ny,n,m; int mat[maxn][maxn]; struct node { int x,y; }point1[maxn],point2[maxn]; bool dfs(int x) { visx[x]=1; for(int y=1;y<=ny;y++) { if(visy[y]) continue; int temp=lx[x]+ly[y]-mat[x][y]; if(temp==0)//可行边,在相等子图里 { visy[y]=1; if(mark[y]==-1 || dfs(mark[y])) { mark[y]=x; return true; } } else if(slack[y]>temp) slack[y]=temp; } return false; } int KM() { memset(ly,0,sizeof(ly)); memset(mark,-1,sizeof(mark)); for(int x=1;x<=nx;x++) { lx[x]=-inf; for(int i=1;i<=ny;i++) if(lx[x]<mat[x][i]) lx[x]=mat[x][i]; } for(int x=1;x<=nx;x++) { for(int y=1;y<=ny;y++) slack[y]=inf; while(1) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(dfs(x)) break; int d=inf; for(int y=1;y<=ny;y++) if(!visy[y] && d>slack[y]) d=slack[y]; for(int i=1;i<=nx;i++) if(visx[i]) lx[i]-=d; for(int i=1;i<=ny;i++) if(visy[i]) ly[i]+=d; else slack[i]-=d; } } int ans=0; for(int i=1;i<=ny;i++) if(mark[i]!=-1) ans+=mat[mark[i]][i]; return abs(ans); } int main() { while(~scanf("%d%d",&n,&m)) { if(n==0 && m==0) break; nx=ny=0; for(int i=0;i<n;i++) { scanf("%s",str[i]); for(int j=0;j<m;j++) if(str[i][j]=='H') { point2[++ny].x=i; point2[ny].y=j; } else if(str[i][j]=='m') { point1[++nx].x=i; point1[nx].y=j; } } for(int i=1;i<=nx;i++) for(int j=1;j<=ny;j++) mat[i][j]=-abs(point1[i].x-point2[j].x)-abs(point1[i].y-point2[j].y); printf("%d\n",KM()); } return 0; }