1 /* 2 将 maxn 定位 200 不是超时 就是wa 定位300 32ms 过 纠结。。。。。。。 3 4 题意:一个row*col的矩阵,m表示人,H表示房子,.表示空地,人数和房子数相等,如下图: 5 5 5 6 HH..m 7 ..... 8 ..... 9 ..... 10 mm..H 11 现在要让所有的人都进入不同的房子内,问总共最少走多少步? 12 将 人看作是 源点 房子 看作是 汇点 13 14 思路:最小费用最大流。 15 16 */ 17 18 #include<stdio.h> 19 #include<string.h> 20 #define maxn 300 21 #define inf 0x7fffffff 22 #include<cmath> 23 int min(int x,int y) 24 { 25 if(x<y)return x; 26 else return y; 27 } 28 struct node 29 { 30 int x; 31 int y; 32 }h[maxn],man[maxn]; 33 int map[maxn][maxn],vis[maxn],cap[maxn][maxn],dis[maxn]; 34 int que[maxn],pre[maxn]; 35 int num,ans; 36 int SPFA() 37 { 38 39 int i; 40 memset(vis,0,sizeof(vis)); 41 for(i=0;i<=num;i++)dis[i]=inf; 42 dis[0]=0; 43 vis[0]=1; 44 45 int head=0,tail=0; 46 que[0]=0; 47 tail++; 48 while(head!=tail) 49 { 50 int k=que[head]; 51 52 vis[k]=0; 53 for(i=0;i<=num;i++) 54 { 55 if(cap[k][i]&&dis[i]>dis[k]+map[k][i]) 56 { 57 dis[i]=dis[k]+map[k][i]; 58 pre[i]=k; 59 60 if(!vis[i]) 61 { 62 vis[i]=1; 63 que[tail++]=i; 64 if(tail==maxn)tail=0; 65 } 66 } 67 } 68 head++; 69 if(head==maxn)head=0; 70 71 } 72 if(dis[num]<inf)return 1;//这里要注意 和最大流的不同 73 else 74 return 0; 75 } 76 void end() 77 { 78 int i,sum=inf; 79 for(i=num;i!=0;i=pre[i]) 80 { 81 sum=min(sum,cap[pre[i]][i]); 82 } 83 for(i=num;i!=0;i=pre[i]) 84 { 85 cap[pre[i]][i]-=sum; 86 cap[i][pre[i]]+=sum; 87 ans+=map[pre[i]][i]*sum; 88 } 89 90 } 91 int main() 92 { 93 int hnum,mnum,n,m,i,j; 94 char c; 95 while(scanf("%d%d",&n,&m)!=EOF) 96 { 97 if(n==0&&m==0)break; 98 hnum=0; 99 mnum=0; 100 getchar(); 101 for(i=0;i<n;i++) 102 { 103 for(j=0;j<m;j++) 104 { 105 scanf("%c",&c); 106 if(c=='H') 107 { 108 h[++hnum].x=i; 109 h[hnum].y=j; 110 } 111 if(c=='m') 112 { 113 man[++mnum].x=i; 114 man[mnum].y=j; 115 } 116 } 117 getchar(); 118 } 119 memset(cap,0,sizeof(cap)); 120 memset(map,0,sizeof(map)); 121 for(i=1;i<=mnum;i++) 122 { 123 124 for(j=1;j<=hnum;j++) 125 { 126 127 cap[i][j+mnum]=1; 128 map[i][j+mnum]=fabs(man[i].x-h[j].x)+fabs(man[i].y-h[j].y); 129 map[j+mnum][i]=-map[i][j+mnum]; 130 } 131 } 132 num=mnum+hnum+1; 133 for(i=1;i<=mnum;i++) 134 { 135 map[0][i]=map[i][0]=0; 136 cap[0][i]=1; 137 138 } 139 for(i=mnum+1;i<num;i++) 140 { 141 map[i][num]=map[num][i]=0; 142 cap[i][num]=1; 143 } 144 ans=0; 145 while(SPFA())end(); 146 printf("%d\n",ans); 147 148 149 } 150 }