在一个地图上给出房子的位置和人的位置,人和房子的数量是相等的。人要回到房子里,每个房子只能回一个人。人向房子每移动一个单位需要花费$1,求人全部回房子的最小花费。
ACcode:
#pragma warning(disable:4786)//使命名长度不受限制 #pragma comment(linker, "/STACK:102400000,102400000")//手工开栈 #include <map> #include <set> #include <queue> #include <cmath> #include <stack> #include <cctype> #include <cstdio> #include <cstring> #include <stdlib.h> #include <iostream> #include <algorithm> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define rds(x) scanf("%s",x) #define rdc(x) scanf("%c",&x) #define ll long long int #define maxn 105 #define mod 1000000007 #define INF 0x3f3f3f3f //int 最大值 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i) #define MT(x,i) memset(x,i,sizeof(x)) #define PI acos(-1.0) #define E exp(1) using namespace std; struct P{int x,y;}; P man[maxn],house[maxn]; int mm,hh,n,m,res; int a[maxn],b[maxn],match[maxn],slack[maxn],mp[maxn][maxn]; bool visa[maxn],visb[maxn]; char str[maxn]; bool find_path(int u){ visa[u]=true; FOR(j,0,hh-1){ if(!visb[j]&&a[u]+b[j]==mp[u][j]){ visb[j]=true; if(match[j]==-1||find_path(match[j])){ match[j]=u; return true; } } else if(a[u]+b[j]>mp[u][j]) slack[j]=min(slack[j],a[u]+b[j]-mp[u][j]); } return false; } void km(){ MT(a,0);MT(b,0);MT(match,-1); FOR(i,0,mm-1) FOR(j,0,hh-1) a[i]=max(mp[i][j],a[i]); FOR(i,0,mm-1){ FOR(j,0,hh-1)slack[j]=INF; while(true){ FOR(j,0,maxn){visa[j]=visb[j]=0;} if(find_path(i))break; int d=INF; FOR(j,0,hh-1) if(!visb[j]&&d>slack[j])d=slack[j]; FOR(j,0,mm-1) if(visa[j])a[j]-=d; FOR(j,0,hh-1) if(visb[j])b[j]+=d; else slack[j]-=d; } } } int main(){ while(rd2(n,m)&&(n+m)){ hh=mm=res=0; FOR(i,0,n-1){ rds(str); FOR(j,0,m-1){ if(str[j]=='H'){ house[hh].x=i; house[hh++].y=j; }else if(str[j]=='m'){ man[mm].x=i; man[mm++].y=j; } } } FOR(i,0,mm-1) FOR(j,0,hh-1) mp[i][j]=-(abs(man[i].x-house[j].x)+abs(man[i].y-house[j].y)); km(); FOR(j,0,hh-1) res-=mp[match[j]][j]; printf("%d\n",res); } return 0; } /* 2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0 */