//hdu 1533 Going Home(二分KM算法)
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int N=110;
const int Inf=1<<30;
struct node
{
int x,y;
}M[N],H[N];
int mm,hh;
char mp[N][N];
int n,m;
int w[N][N];
int lx[N],ly[N];//顶标
int father[N],slack[N];
bool sy[N],sx[N];
int ABS(int a)
{
return a>0?a:-a;
}
int Min(int a,int b){return a<b?a:b;}
int Max(int a,int b){return a>b?a:b;}
int dis(node a,node b)
{
return ABS(a.x-b.x)+ABS(a.y-b.y);
}
void init()
{
mm=0;hh=0;
memset(w,0,sizeof(w));
}
void buildmap()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mp[i][j]=='m')
{
M[mm].x=i;
M[mm].y=j;
mm++;
}
if(mp[i][j]=='H')
{
H[hh].x=i;
H[hh].y=j;
hh++;
}
}
}
for(int i=0;i<mm;i++)
{
for(int j=0;j<hh;j++)
{
w[i][j]=-dis(M[i],H[j]);
}
}
}
//============KM核心算法================
bool dfs(int from)
{
sx[from]=true;
for(int i=0;i<hh;i++)
{
if(sy[i]) continue;
int temp=lx[from]+ly[i]-w[from][i];
if(!temp)
{
sy[i]=true;
if(father[i]==-1||dfs(father[i]))
{
father[i]=from;
//cout<<i<<endl;
return true;
}
}
else if(slack[i]>temp)
{
slack[i]=temp;
}
}
return false;
}
int KM()
{
int ans;
memset(father,-1,sizeof(father));
memset(ly,0,sizeof(ly));
for(int i=0;i<mm;i++)
{
lx[i]=-Inf;
for(int j=0;j<hh;j++)
{
lx[i]=Max(lx[i],w[i][j]);
}
}
for(int i=0;i<mm;i++)
{
for(int j=0;j<hh;j++)
{
slack[j]=Inf;
}
while(1)
{
memset(sx,false,sizeof(sx));
memset(sy,false,sizeof(sy));
if(dfs(i)) break;
int df=Inf;
for(int ii=0;ii<hh;ii++)
{
if(!sy[ii]) df=Min(df,slack[ii]);
}
for(int ii=0;ii<mm;ii++)
{
if(sx[ii]) lx[ii]-=df;
}
for(int ii=0;ii<hh;ii++)
{
if(sy[ii]) ly[ii]+=df;
}
}
/* for(int i=0;i<hh;i++)
{
cout<<father[i]<<" "<<i<<endl;
}*/
}
ans=0;
for(int i=0;i<hh;i++)
{
ans+=w[father[i]][i];
}
return -ans;
}
//===============================
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
init();
for(int i=0;i<n;i++)
{
scanf("%s",mp[i]);
}
buildmap();
printf("%d\n",KM());
}
return 0;
}
hdu 1533 Going Home(二分KM算法)
最新推荐文章于 2019-07-08 08:46:35 发布