题目链接:POJ 2195 Going Home
人是可以踩踏房子经过的,那距离就很好求了。建图求距离,把距离设为负的,就转化为KM了,最后别忘了负号。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAX_N = 100 + 30;
const int INF = 0x3f3f3f3f;
int n_x, n_y;//两边的点数
int G[MAX_N][MAX_N];//二分图权值
int link[MAX_N], l_x[MAX_N], l_y[MAX_N];//y中各店匹配的状态, x,y,中的点标号
int slack[MAX_N];
bool vis_x[MAX_N], vis_y[MAX_N];
bool DFS(int x)
{
vis_x[x] = true;
for(int y = 0; y < n_y; y++)
{
if(vis_y[y])
continue;
int temp = l_x[x] + l_y[y] - G[x][y];
if(temp == 0)
{
vis_y[y] = true;
if(link[y] == -1 || DFS(link[y]))
{
link[y] = x;
return true;
}
}
else if(slack[y] > temp)
slack[y] = temp;
}
return false;
}
int KM()
{
memset(link, -1, sizeof(link));
memset(l_y, 0, sizeof(l_y));
for(int i = 0; i < n_x; i++)
{
l_x[i] = -INF;
for(int j = 0; j < n_y; j++)
if(G[i][j] > l_x[i])
l_x[i] = G[i][j];
}
for(int x = 0; x < n_x; x++)
{
for(int i = 0; i < n_y; i++)
slack[i] = INF;
while(true)
{
memset(vis_x, false, sizeof(vis_x));
memset(vis_y, false, sizeof(vis_y));
if(DFS(x))
break;
int d = INF;
for(int i = 0; i < n_y; i++)
if(!vis_y[i] && d > slack[i])
d = slack[i];
for(int i = 0; i < n_y; i++)
if(vis_x[i])
l_x[i] -= d;
for(int i = 0; i < n_y; i++)
{
if(vis_y[i])
l_y[i] += d;
else
slack[i] -= d;
}
}
}
int res = 0;
for(int i = 0; i < n_y; i++)
if(link[i] != -1)
res += G[link[i]][i];
return res;
}
char _map[MAX_N][MAX_N];
struct Man
{
int x, y;
};
struct House
{
int x, y;
};
Man man[MAX_N];
House house[MAX_N];
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF && n + m)
{
for(int i = 0; i < n; i++)
scanf("%s", _map[i]);
int cnt_man = 0, cnt_house = 0;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(_map[i][j] == 'm')
{
man[cnt_man].x = i;
man[cnt_man++].y = j;
}
else if(_map[i][j] == 'H')
{
house[cnt_house].x = i;
house[cnt_house++].y = j;
}
}
}
n_x = cnt_man;
n_y = cnt_house;
for(int i = 0; i < cnt_man; i++)
for(int j = 0; j < cnt_house; j++)
G[i][j] = -(abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y));
printf("%d\n", -KM());
}
return 0;
}