给出一个 n∗ m 的字符串,其中 m 代表是人,H 代表的房子,代表立足地,每个人只能上/下/左/右移动。移动一步的花费是 1。问: 让所有人移动到房子(每个房子里面只能容纳一个人)里面的最小花费是多少?
最小费用最大流模板~
#include<cstdio> #include<iostream> #include<algorithm> #include<string> #include<queue> #include<cstring> using namespace std; const int maxn=1014; const int inf=1e9; int cap[maxn][maxn]; int flow[maxn][maxn]; int cost[maxn][maxn]; int n; int f; int c; int st,ed; bool visit[maxn]; int pre[maxn]; int d[maxn]; bool spfa () { queue<int> q; fill (d,d+maxn,inf); fill (visit,visit+maxn,false); d[st]=0; visit[st]=true; q.push(st); while (!q.empty()) { int u=q.front(); visit[u]=false; q.pop(); for (int v=0;v<=n;v++) { if (cap[u][v]>flow[u][v]&&d[v]>d[u]+cost[u][v]) { d[v]=d[u]+cost[u][v]; pre[v]=u; if (!visit[v]) { visit[v]=true; q.push(v); } } } } if (d[ed]>=inf) return false; return true; } void minCostMaxflow () { memset (flow,0,sizeof(flow)); c=f=0; while (spfa()) { int Min=inf; for (int u=ed;u!=st;u=pre[u]) Min=min(Min,cap[pre[u]][u]-flow[pre[u]][u]); for (int u=ed;u!=st;u=pre[u]) { flow[pre[u]][u]+=Min; flow[u][pre[u]]-=Min; } c+=d[ed]*Min; f+=Min; } } struct node { int x,y; }Node1[maxn],Node2[maxn]; string s[maxn]; int main () { int N,M; while (scanf("%d %d",&N,&M)) { if (N==0&&M==0) break; int tol1=0,tol2=0; for (int i=0;i<N;i++) { cin>>s[i]; for (int j=0;j<M;j++) { if (s[i][j]=='m') { tol1++; Node1[tol1].x=i; Node1[tol1].y=j; } else if (s[i][j]=='H') { tol2++; Node2[tol2].x=i; Node2[tol2].y=j; } } } st=0; n=tol1+tol2+1; ed=tol1+tol2+1; memset(cap,0,sizeof(cap)); memset(cost,0,sizeof(cost)); for (int i=1;i<=tol1;i++) { cost[0][i]=cost[i][0]=0; cap[0][i]=1; } for (int i=1;i<=tol2;i++) { cost[tol1+i][ed]=0; cap[tol1+i][ed]=1; } for (int i=1;i<=tol1;i++) for (int j=1;j<=tol2;j++) { cost[i][tol1+j]=abs(Node1[i].x-Node2[j].x)+abs(Node1[i].y-Node2[j].y); cost[tol1+j][i]=-cost[i][tol1+j]; cap[i][tol1+j]=1; } minCostMaxflow(); printf ("%d ",c); } return 0; }