标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 20115 | Accepted: 10189 |
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
题解:这个题意就是,m个人都进入不同的房子的步数和最小;那么求负的步数的最大匹配就可以了;km算法;
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define mem(x,y) memset(x,y,sizeof(x)) 7 const int MAXN=110; 8 const int INF=1e4; 9 char s[MAXN][MAXN]; 10 int mp[MAXN][MAXN],lx[MAXN],ly[MAXN],usdx[MAXN],usdy[MAXN],mat[MAXN]; 11 struct Node{ 12 int x,y; 13 }hou[MAXN],man[MAXN]; 14 int k; 15 bool dfs(int x){ 16 usdx[x]=1; 17 for(int i=1;i<=k;i++){ 18 if(!usdy[i]&&lx[x]+ly[i]==mp[x][i]){ 19 usdy[i]=1; 20 if(!mat[i]||dfs(mat[i])){ 21 mat[i]=x;return true; 22 } 23 } 24 } 25 return false; 26 } 27 int km(){ 28 mem(mat,0);mem(lx,0);mem(ly,0); 29 for(int i=1;i<=k;i++) 30 for(int j=1;j<=k;j++) 31 lx[i]=max(lx[i],mp[i][j]); 32 for(int i=1;i<=k;i++){ 33 mem(usdx,0);mem(usdy,0); 34 while(!dfs(i)){ 35 int d=INF; 36 for(int j=1;j<=k;j++) 37 if(usdx[j]) 38 for(int b=1;b<=k;b++) 39 if(!usdy[b]) 40 d=min(d,lx[j]+ly[b]-mp[j][b]); 41 for(int j=1;j<=k;j++){ 42 if(usdx[j])lx[j]-=d; 43 if(usdy[j])ly[j]+=d; 44 } 45 mem(usdx,0);mem(usdy,0); 46 } 47 }int ans=0; 48 for(int i=1;i<=k;i++)ans+=lx[i]+ly[i]; 49 return INF*k-ans; 50 } 51 int main(){ 52 int N,M; 53 while(scanf("%d%d",&N,&M),N|M){ 54 int k1=0,k2=0; 55 for(int i=0;i<N;i++){ 56 scanf("%s",s[i]); 57 for(int j=0;j<M;j++){ 58 if(s[i][j]==‘H‘)hou[++k1].x=i,hou[k1].y=j; 59 if(s[i][j]==‘m‘)man[++k2].x=i,man[k2].y=j; 60 } 61 }k=k1; 62 // printf("%d %d\n",k1,k2); 63 for(int i=1;i<=k;i++) 64 for(int j=1;j<=k;j++) 65 mp[i][j]=INF-(abs(hou[i].x-man[j].x)+abs(hou[i].y-man[j].y));//这样是因为要找最小的距离,所以把距离变成负的+INF找最大匹配就行了; 66 printf("%d\n",km()); 67 } 68 return 0; 69 }
标签:
原文地址:http://www.cnblogs.com/handsomecui/p/4960445.html