hdu2195Going Home【最小费用最大流】

Going Home










Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 17230   Accepted: 8781

Description

On a grid map there are n little men and n houses.
In each unit time, every little man can move one unit step, either horizontally,
or vertically, to an adjacent point. For each little man, you need to pay a $1
travel fee for every step he moves, until he enters a house. The task is
complicated with the restriction that each house can accommodate only one little
man. 

Your task is to compute the minimum amount of money you need
to pay in order to send these n little men into those n different houses. The
input is a map of the scenario, a ‘.‘ means an empty space, an ‘H‘ represents a
house on that point, and am ‘m‘ indicates there is a little man on that
point. 


You can
think of each point on the grid map as a quite large square, so it can hold n
little men at the same time; also, it is okay if a little man steps on a grid
with a house without entering that house.

Input

There are one or more test cases in the input.
Each case starts with a line giving two integers N and M, where N is the number
of rows of the map, and M is the number of columns. The rest of the input will
be N lines describing the map. You may assume both N and M are between 2 and
100, inclusive. There will be the same number of ‘H‘s and ‘m‘s on the map; and
there will be at most 100 houses. Input will terminate with 0 0 for N and
M.

Output

For each test case, output one line with the
single integer, which is the minimum amount, in dollars, you need to pay.

Sample Input

2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0

Sample Output

2
10
28

Source

Pacific
Northwest 2004

题意:

5 5
HH..m
.....
.....
.....
mm..H
对于一个图
m代表人H代表房间
现在需要用最少的步数将所有的人送回房间,问最小步数是多少,每个房间只能容纳一个人

分析:
每个人到每个房间的花费我们可以求出来

现在,我们把人和花费都抽象成一个一个的点,将人和房间连一条花费为步数的边

那么求出最小费用最大流即可

代码:

  1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <vector>
5 #include <cmath>
6 #include <queue>
7 using namespace std;
8
9 const int maxn = 1005;
10
11 typedef pair<int, int> PII;
12
13 char a[maxn][maxn];
14 vector<PII>v[2];
15 const int INF = 1000000000;
16
17 struct Edge {
18 int from, to, cap, flow, cost;
19 };
20
21 struct MCMF
22 {
23 int n, m, s, t;
24 vector<Edge> edges;
25 vector<int> G[maxn];
26
27 int inq[maxn];
28 int d[maxn];
29 int p[maxn];
30 int a[maxn];
31
32 void init(int n) {
33 this -> n = n;
34 for(int i = 0; i < n; i++) G[i].clear();
35 edges.clear();
36 }
37
38 void AddEdge(int from, int to, int cap, int cost) {
39 edges.push_back((Edge) { from, to, cap, 0, cost } );
40 edges.push_back((Edge) { to, from, 0, 0, -cost } );
41 m = edges.size();
42 G[from].push_back(m - 2);
43 G[to].push_back(m - 1);
44 }
45
46 bool BellmanFord(int s, int t, int &flow, int &cost) {
47 for(int i = 0; i < n; i++) d[i] = INF;
48 memset(inq, 0, sizeof(inq) );
49 d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
50 queue<int> Q;
51 Q.push(s);
52 while(!Q.empty()) {
53 int u = Q.front(); Q.pop();
54 inq[u] = 0;
55 for(int i = 0; i < G[u].size(); i++) {
56 Edge &e = edges[G[u][i]];
57 if(e.cap > e.flow && d[e.to] > d[u] + e.cost) {
58 d[e.to] = d[u] + e.cost;
59 p[e.to] = G[u][i];
60 a[e.to] = min(a[u], e.cap - e.flow);
61 if(!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }
62 }
63 }
64 }
65
66 if(d[t] == INF) return false;
67 flow += a[t];
68 cost += d[t] * a[t];
69 int u = t;
70 while(u != s) {
71 edges[p[u]].flow += a[t];
72 edges[p[u] ^ 1].flow -= a[t];
73 u = edges[p[u]].from;
74 }
75 return true;
76 }
77
78 int MinCost(int s, int t) {
79 //this -> s = s; this -> t = t;
80 int flow = 0, cost = 0;
81 while(BellmanFord(s, t, flow, cost)){};
82 return cost;
83 }
84 };
85
86 MCMF g;
87
88 int get_dist(PII p1, PII p2) {
89 return fabs(p1.first - p2.first) + fabs(p1.second - p2.second);
90 }
91
92 int main() {
93 int n, m;
94 //freopen("a.txt","r",stdin);
95 while(scanf("%d %d",&n, &m)) {
96 if(n == 0 && m == 0)
97 break;
98 //puts("*");
99 int m_num = 0, H_num = 0;
100 for(int i = 0; i < 2; i++) {
101 v[i].clear();
102 }
103 g.init(n * m);//节点个数 尽量大一点
104 for(int i = 0; i < n; i++) {
105 for(int j = 0; j < m; j++) {
106 scanf("\n%c",&a[i][j]);//
107 if(a[i][j] == ‘m‘) {
108 m_num++;
109 v[0].push_back(make_pair(i, j));//用vector把所有的人和房间都储存下来
110 }
111 else if(a[i][j] == ‘H‘) {
112 H_num++;
113 v[1].push_back(make_pair(i, j));
114 }
115 }
116 }
117 int s = 0; int t = m_num + H_num + 1;
118 //printf("%d %d %d %d\n",m_num, H_num, v[0].size(), v[1].size());
119 for(int i = 1; i <= m_num; i++) {
120 g.AddEdge(s, i, 1, 0);//源点跟人的容量为1 花费为 0 因为 只能输送一个人
121 }
122 for(int i = m_num + 1; i <= m_num + H_num; i++) {
123 g.AddEdge(i, t, 1, 0);//同理
124 }
125
126 for(int i = 0; i < v[0].size(); i++) {
127 for(int j = 0; j < v[1].size(); j++) {
128 g.AddEdge(i + 1, m_num + j + 1, 1, get_dist(v[0][i], v[1][j]));//容量为1 花费为步数
129 }
130 }
131 printf("%d\n",g.MinCost(s, t)) ;
132 }
133 return 0;
134 }

hdu2195Going Home【最小费用最大流】,布布扣,bubuko.com

时间: 2024-08-04 17:17:53

hdu2195Going Home【最小费用最大流】的相关文章

【BZOJ3876】【Ahoi2014】支线剧情 有下界的最小费用最大流

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43025375"); } [BZOJ2324]营救皮卡丘 这道题也是一道有下界的最小费用最大流. 我的题解地址:http://blog.csdn.net/vmurder/article/details/41378979 这道题其实就是模板题. 我的处理

POJ 3686.The Windy&#39;s 最小费用最大流

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5477   Accepted: 2285 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys. The ma

P3381 【模板】最小费用最大流

P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的

C++之路进阶——最小费用最大流(支线剧情)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 332[Submit

hdu 4494 Teamwork 最小费用最大流

Teamwork Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4494 Description Some locations in city A has been destroyed in the fierce battle. So the government decides to send some workers to repair these location

POJ - 2195 Going Home(最小费用最大流)

1.N*M的矩阵中,有k个人和k个房子,每个人分别进入一个房子中,求所有人移动的最小距离. 2.人看成源点,房子看成汇点,求最小费用最大流. 建图-- 人指向房子,容量为1,费用为人到房子的曼哈顿距离. 建立超级源点和超级汇点:超级源点指向人,容量为1,费用为0:超级汇点指向房子,容量为1,费用为0. 求超级源点到超级汇点的最小费用最大流即可. ps:容量为什么都设为1?---有待研究.. 3. 1.Bellman-Ford: #include<iostream> #include<st

hdu 1853 Cyclic Tour 最小费用最大流

题意:一个有向图,现在问将图中的每一个点都划分到一个环中的最少代价(边权和). 思路:拆点,建二分图,跑最小费用最大流即可.若最大流为n,则说明是最大匹配为n,所有点都参与,每个点的入度和出度又是1,所以就是环. /********************************************************* file name: hdu1853.cpp author : kereo create time: 2015年02月16日 星期一 17时38分51秒 *******

最小费用最大流

Farm Tour http://poj.org/problem?id=2135 建图再说吧 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<map> 6 #include<stack> 7 #include<queue> 8 #include<vector> 9 #include&l

POJ 2195 地图的最小费用最大流

思路:这题刚开始看就知道是最小费用最大流了,因为求出最优嘛,而且要m,H要一一对应,所以不是二分图匹配就是最小费用最大流. 不过,刚开始还在想每个m与H之间的最小花费如何求,难道要用dfs搜索吗?这样想之后看了下题目给的时间是1000ms,然后就把dfs搜索m与H之间的最短距离排除了.然后想了想,其实尼玛太简单了,因为题目说了只能垂直与竖直的走,所以最短距离不就是两个横坐标相减与两个纵坐标相减之和嘛! 然后每对m与H之间都连边,流量为1(因为每对匹配不能重复),费用为它们之间的距离即花费:然后建