題目:http://poj.org/problem?id=2195
原始碼:
#include <stdio.h>#define INF 1e9#define MAXN 150#define N 300#define M 30000int n,m;int numH,numM,num,ans;char str[MAXN][MAXN];int Hx[MAXN],Hy[MAXN],Mx[MAXN],My[MAXN];int min(int a,int b){ return a>b?b:a;}struct MinCostMaxFlow { int e, ev[M], nxt[M], head[N]; int cost[M], dist[N]; int cap[M]; int pnt[N], road[N], q[N], bg, ed; bool vis[N]; void init(int n) { e = 0; for(int i=0;i<=n;i++) head[i]=-1; } void addedge(int u, int v, int f, int c) { //u->v flow=f, cost=c ev[e]=v; cap[e]=f; cost[e]=c; nxt[e]=head[u]; head[u]=e++; ev[e]=u; cap[e]=0; cost[e]=-c; nxt[e]=head[v]; head[v]=e++; } bool spfa(int s, int t, int n) { for(int i=0;i<=n;i++) { dist[i]=INF; vis[i]=0; } bg = ed = dist[s] = 0; pnt[s] = s; q[ed++] = s; while (bg != ed) { int u = q[bg++]; vis[u] = 0; if (bg == N) bg = 0; for (int i = head[u]; ~i; i = nxt[i]) { if (cap[i] <= 0) continue; int v = ev[i]; if (dist[v] > dist[u] + cost[i]) { dist[v] = dist[u] + cost[i]; pnt[v] = u; road[v] = i; if (!vis[v]) { q[ed++] = v; vis[v] = 1; if(ed == N)ed = 0; } } } } return dist[t] != INF;} void mincost(int s, int t, int n, int &f, int &c) { c = f = 0; while(spfa(s, t, n)){ int minf = INF; for(int u = t; u != s; u = pnt[u]) minf = min(minf, cap[road[u]]); for(int u = t; u != s; u = pnt[u]){ cap[road[u]] -= minf; cap[road[u] ^ 1] += minf; } f += minf; c += minf * dist[t]; } }};int abs(int a){ if(a<0) return -a; return a;}int solve(){ MinCostMaxFlow tmp; int ans,ans1,d; tmp.init(2*num+2); for(int i=0;i<num;i++) tmp.addedge(0,i+1,1,0); for(int i=0;i<num;i++) tmp.addedge(i+1+num,2*num+1,1,0); for(int i=0;i<num;i++) for(int j=0;j<num;j++) { d=abs(Hx[i]-Mx[j])+abs(Hy[i]-My[j]); tmp.addedge(i+1,j+1+num,INF,d); } tmp.mincost(0,2*num+1,2*num+2,ans1,ans); return ans;}int main(){ freopen("D:\\a.txt","r",stdin); while(true) { scanf("%d %d",&n,&m); if(!m&&!n) break; for(int i=0;i<n;i++) scanf("%s",str[i]); numH=0; numM=0; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(str[i][j]=='H') { Hx[numH]=i; Hy[numH]=j; numH++; } if(str[i][j]=='m') { Mx[numM]=i; My[numM]=j; numM++; } } if(numH==numM) num=numH; ans=solve(); printf("%d\n",ans); }}