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"stdio.h" #include"string.h" #include"math.h" #define N 105 #define mmax(a,b) ((a)>(b)?(a):(b)) #define mmin(a,b) ((a)<(b)?(a):(b)) const int inf=0x7fffffff; int g[N][N],slack[N]; int link[N],lx[N],ly[N]; int visx[N],visy[N],n; struct node { int x,y; }h[N],man[N]; int find(int k,int n) { visx[k]=1; int i,d; for(i=0;i<n;i++) { if(visy[i]) continue; d=lx[k]+ly[i]-g[k][i]; if(d==0) { visy[i]=1; if(link[i]==-1||find(link[i],n)) { link[i]=k; return 1; } } else slack[i]=mmin(slack[i],d); } return 0; } int KM(int n) { int i,j; memset(lx,0,sizeof(lx)); memset(ly,0,sizeof(ly)); memset(link,-1,sizeof(link)); for(i=0;i<n;i++) { for(j=0;j<n;j++) { lx[i]=mmax(lx[i],g[i][j]); } } for(i=0;i<n;i++) { for(j=0;j<n;j++) { slack[j]=inf; } while(1) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(find(i,n)) break; else { int d=inf; for(j=0;j<n;j++) { if(!visy[j]) { d=mmin(d,slack[j]); } } for(j=0;j<n;j++) { if(visx[j]) lx[j]-=d; if(visy[j]) ly[j]+=d; } } } } int ans=0; for(i=0;i<n;i++) { ans+=g[link[i]][i]; } return ans; } int main() { int i,j,n,m; char str[N][N]; while(scanf("%d%d",&n,&m),n||m) { int n1,n2; n1=n2=0; for(i=0;i<n;i++) { scanf("%s",str[i]); for(j=0;j<m;j++) { if(str[i][j]=='H') { h[n1].x=i; h[n1++].y=j; } if(str[i][j]=='m') { man[n2].x=i; man[n2++].y=j; } } } for(i=0;i<n1;i++) { for(j=0;j<n2;j++) //求出两点间的曼哈顿距离,即建图 { g[i][j]=-abs(h[i].x-man[j].x)-abs(h[i].y-man[j].y); } } printf("%d\n",-KM(n1)); } return 0; }
hdu 1533 Going Home (KM算法),布布扣,bubuko.com
原文:http://blog.csdn.net/u011721440/article/details/38170709