(最小费用流的入门基础题)
题目大概意思为在一个矩阵中,有n个小人和n个房子,小人每走一格花费1美元,小人只能上下左右走,且可以经过房子但不进去,为了让每个小人有自己的房子,求最小费用
首先统计每个小人去每个房子分别最少需要多少钱, 小人到房子所需费用等于两者的横坐标差的绝对值加上纵坐标差的绝对值。然后把小人与房子之间连上一条容量为1,费用为到达所需费用的值
然后套最小费用流模板即可
(其他细节我就注释在代码中)
#include <iostream>
#include <stdio.h>
#include <utility>
#include <stdlib.h>
#include <vector>
#define INF 1000000005
using namespace std;
vector<pair<int, int> > flag1; //用于放房子的位置
vector<pair<int, int> > flag2; //用于放小人的位置
int N, M, n, data[105][105];
struct edge
{
int to, cap, coust, rev;
edge(int t, int c, int s, int r)
{
to = t; cap = c; coust = s; rev = r;
}
};
vector<struct edge> ddd[205];
int dist[205];
int prev[205];
int prep[205];
char ch;
void add_edge(int i, int j, int k)
{
ddd[i].push_back(edge(j, 1, k, ddd[j].size()));
ddd[j].push_back(edge(i, 0, -k, ddd[i].size() - 1));
}
int min_coust(int from, int to, int flow)
{
int money = 0;
while(flow--)
{
fill(dist, dist + 2 * n + 2, INF);
dist[from] = 0;
bool flag = true;
while(flag)
{
flag = false;
for(int i = 0; i <= 2 * n + 1; i++)
{
if(dist[i] != INF)
{
for(int j = 0; j < ddd[i].size(); j++)
{
struct edge e = ddd[i][j];
if(e.cap != 0 && dist[i] + e.coust < dist[e.to])
{
flag = true;
dist[e.to] = dist[i] + e.coust;
prev[e.to] = i;
prep[e.to] = j;
}
}
}
}
}
for(int i = to; i != from; i = prev[i])
{
ddd[prev[i]][prep[i]].cap--;
ddd[i][ddd[prev[i]][prep[i]].rev].cap++;
}
money = money + dist[to];
}
return money;
}
int main()
{
while(1)
{
flag1.clear();
flag2.clear();
for(int i = 0; i < 205; i++)
{
ddd[i].clear();
}
scanf("%d %d", &N, &M);
if(N == 0 && M == 0)
{
break;
}
for(int i = 0; i < N; i++)
{
getchar();
for(int j = 0; j < M; j++)
{
scanf("%c", &ch);
if(ch == 'H')
{
data[i][j] = 2;
flag1.push_back(make_pair(i, j));
}
else if(ch == 'm')
{
data[i][j] = 1;
flag2.push_back(make_pair(i, j));
}
else
{
data[i][j] = 0;
}
}
}
n = flag1.size();
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
int num = abs(flag1[i].first - flag2[j].first) + abs(flag1[i].second - flag2[j].second);
add_edge(i + 1, j + n + 1, num);
}
add_edge(0, i + 1, 0);
add_edge(i + n + 1, 2 * n + 1, 0);
}
printf("%d\n", min_coust(0, 2 * n + 1, n));
}
}