题目:http://poj.org/problem?id=2195
处理出每个人到每个门的曼哈顿距离,分别建立容量为1费用为曼哈顿距离的边,在源点和每个人人之间建立容量为1费用为0的边,在门和汇点之间建立容量为1费用为0的边,然后跑最小费用流即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 #include<iostream> 6 #include<stdlib.h> 7 using namespace std; 8 typedef pair<int,int> P; 9 const int maxv = 222; 10 const int inf = 0x3f3f3f3f; 11 struct edge{ 12 int to,cap,cost,rev; 13 }; 14 int V; 15 vector<edge> g[maxv]; 16 int h[maxv]; 17 int dist[maxv]; 18 int prevv[maxv],preve[maxv]; 19 void addedge(int from,int to,int cap,int cost){ 20 edge t; 21 t.to = to;t.cap = cap;t.cost = cost;t.rev = g[to].size(); 22 g[from].push_back(t); 23 t.to = from;t.cap = 0;t.cost = -cost;t.rev = g[from].size()-1; 24 g[to].push_back(t); 25 } 26 int solve(int s,int t,int f){ 27 int res = 0; 28 memset(h,0,sizeof(h)); 29 while(f > 0){ 30 priority_queue<P,vector<P>,greater<P> > que; 31 memset(dist,inf,sizeof(dist)); 32 dist[s] = 0; 33 que.push(P(0,s)); 34 while(!que.empty()){ 35 P p = que.top(); 36 que.pop(); 37 int v = p.second; 38 if(dist[v] < p.first) 39 continue; 40 for(int i = 0;i<g[v].size();i++){ 41 edge &e = g[v][i]; 42 if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){ 43 dist[e.to] = dist[v]+e.cost+h[v]-h[e.to]; 44 prevv[e.to] = v; 45 preve[e.to] = i; 46 que.push(P(dist[e.to],e.to)); 47 } 48 } 49 } 50 if(dist[t] == inf){ 51 return -1; 52 } 53 for(int i = 0;i<=t;i++) 54 h[i] += dist[i]; 55 int d = f; 56 for(int i = t;i!=s;i = prevv[i]){ 57 d = min(d,g[prevv[i]][preve[i]].cap); 58 } 59 f -= d; 60 res += d*h[t]; 61 for(int i = t;i!=s;i = prevv[i]){ 62 edge &e = g[prevv[i]][preve[i]]; 63 e.cap -= d; 64 g[i][e.rev].cap += d; 65 } 66 } 67 return res; 68 } 69 int main(){ 70 int n,m; 71 while(scanf("%d%d",&n,&m) && n && m){ 72 vector<P> mm,hh; 73 char ch; 74 for(int i = 1;i<=n;i++){ 75 for(int j = 1;j<=m;j++){ 76 scanf(" %c",&ch); 77 if(ch == ‘m‘) 78 mm.push_back(P(i,j)); 79 if(ch == ‘H‘) 80 hh.push_back(P(i,j)); 81 } 82 } 83 for(int i = 0;i<=2*mm.size()+1;i++) 84 g[i].clear(); 85 for(int i = 0;i<mm.size();i++){ 86 for(int j = 0;j<hh.size();j++){ 87 addedge(i+1,mm.size()+j+1,1,abs(mm[i].first-hh[j].first)+abs(mm[i].second-hh[j].second)); 88 } 89 } 90 int s = 0,t = 2*mm.size()+1; 91 for(int i = 0;i<mm.size();i++) 92 addedge(s,i+1,1,0); 93 for(int i = 0;i<hh.size();i++) 94 addedge(mm.size()+i+1,t,1,0); 95 cout << solve(s,t,mm.size()) << endl; 96 } 97 }
时间: 2024-10-12 02:07:00