Loli_con

PKu 2195
  1 //PKu 2195 回家 By Loli_con Enail : Loli_con@outlook.com
  2 /*
  3 题目叙述
  4 =========
  5 在一个网格图中,有n个人和n个房子。每一个单位时间,每个小人可以移动一个单位长度,无论水平还是竖直,到临近的点。对于每个人,每移动一步你需要花费1$,直到他移动到他的家,题目限制一个房子仅能住进一个人
  6 你的任务是计算最小花费使得n个人都能住进不同的n个房子。
  7 输入是一张地图,'.'表示空地,'H'表示房子,'m'表示人
  8 你可以认为一个点是足够的大以至于可以同时站上去全部的n个人,当然,一个人也可以站在房子那个点而不进入。
  9 =====================
 10 输入叙述
 11 =====================
 12 多组测试数据。对于每组测试数据
 13 第一行包括两个整数n和m,表示地图是n行m列的。
 14 接下来n行每行m个字符,'.'、'H'、'm'含义如上。2<=n,m<=100,H<=100,
 15 输入数据以0 0结束
 16 =====================
 17 输出叙述
 18 =====================
 19 对于每组测试数据输出一行一个整数最小花费
 20 =====================
 21 样例输入
 22 =====================
 23 2 2
 24 .m
 25 H.
 26 5 5
 27 HH..m
 28 .....
 29 .....
 30 .....
 31 mm..H
 32 7 8
 33 ...H....
 34 ...H....
 35 ...H....
 36 mmmHmmmm
 37 ...H....
 38 ...H....
 39 ...H....
 40 0 0
 41 =====================
 42 样例输出
 43 =====================
 44 2
 45 10
 46 28
 47 =====================
 48 解题报告
 49 =====================
 50 最小费用最大流模版题,KM算法也可解
 51 */
 52 #include <iostream>
 53 #include <cstdio>
 54 #include <algorithm>
 55 #include <string>
 56 #include <cmath>
 57 #include <cstring>
 58 #include <queue>
 59 #define Max 5005
 60 #define inf 1<<28
 61 using namespace std;
 62 struct kdq
 63 {
 64     int x,y;
 65 }human[Max],house[Max];
 66 int n,m;
 67 int S,T;//源点,汇点
 68 int cost[Max/10][Max];//花费
 69 int cap[Max/10][Max];//容量
 70 int dis[Max];
 71 int path[Max];
 72 bool visit[Max];
 73 int q[Max*10];
 74 
 75 int spfa()//最短路
 76 {
 77     int i,j;
 78     for(i=0;i<=T;i++)
 79     dis[i]=inf,path[i]=-1,visit[i]=0;
 80     dis[S]=0;
 81     visit[S]=1;
 82     int num=0,cnt=0;
 83     q[num++]=S;
 84     while(num>cnt)
 85     {
 86         int temp=q[cnt++];
 87         visit[temp]=0;
 88         for(i=0;i<=T;i++)
 89         {
 90             if(cap[temp][i]&&dis[temp]+cost[temp][i]<dis[i])
 91             {
 92                 path[i]=temp;
 93                 dis[i]=dis[temp]+cost[temp][i];
 94                 if(!visit[i])
 95                 {
 96                     q[num++]=i;
 97                     visit[i]=1;
 98                 }
 99             }
100         }
101     }
102     return dis[T]!=inf;
103 }
104 
105 int minCost=0;
106 void getMaxFlow()//增广找最大流
107 {
108     int maxFlow=inf;
109 
110     while(spfa())
111     {
112         int pre=T;
113         while(path[pre]!=-1)
114         {
115             maxFlow=min(maxFlow,cap[path[pre]][pre]);
116             pre=path[pre];
117         }
118         pre=T;
119         minCost+=dis[T]*maxFlow;//最小费用
120         while(path[pre]!=-1)//更新流
121         {
122             cap[path[pre]][pre]-=maxFlow;
123             cap[pre][path[pre]]+=maxFlow;
124             //minCost+=cost[path[pre]][pre]*maxFlow;
125             pre=path[pre];
126         }
127     }
128     cout<<minCost<<endl;
129     return ;
130 }
131 
132 int getdis(kdq x,kdq y)//两个坐标之间的费用
133 {
134     return (abs(x.x-y.x)+abs(y.y-x.y));
135 }
136 void build_map(int numm,int numh)//建图
137 {
138     int i,j;
139     for(i=1;i<=numm;i++)//计算房子和人之间的费用
140     for(j=1;j<=numh;j++){
141         cost[i][j+numm]=getdis(human[i],house[j]);
142         cost[j+numm][i]=-cost[i][j+numm];//负费用用来回流
143     }
144     for(i=1;i<=numm;i++)//源点到每个人的cap,cost
145         cap[S][i]=1,cost[S][i]=0;
146     for(i=1;i<=numh;i++)//房子到汇点的cap,cost
147         cap[i+numm][T]=1;
148     for(i=1;i<=numm;i++)//每个人和房子之间的cap
149     for(j=1;j<=numh;j++)
150     cap[i][j+numm]=1;
151 }
152 int main()
153 {
154     int i,j,k,l;
155     char x;
156     while(scanf("%d%d",&n,&m),(n+m))
157     {
158         memset(cap,0,sizeof(cap));
159         memset(cost,0,sizeof(cost));
160 
161         int numm=0,numh=0;
162         for(i=1;i<=n;i++)
163         for(j=1;j<=m;j++)
164         {
165             cin>>x;
166             if(x=='m'){
167                 human[++numm].x=i;
168                 human[numm].y=j;
169             }
170             if(x=='H'){
171                 house[++numh].x=i;
172                 house[numh].y=j;
173             }
174         }
175         S=0;
176         minCost=0;
177         T=numm+numh+1;//其实numm==numh。。。。
178         build_map(numm,numh);
179         getMaxFlow();
180         }
181     return 0;
182 }

 

posted on 2013-11-30 21:29  Loli_con  阅读(746)  评论(0)    收藏  举报