poj 2195 Going Home (km匹配~~)

Going Home
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 24515   Accepted: 12296

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. 
<center> </center>
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

                   就是让你分别给n个男人找到去n个房子的最短路线~~我们可以把男人和房子分别归为一类~把人和各个房子的最短距离当作边权~~这样的话就是让你找到一个边权越短越好的路径了~这样的话就可以看成最佳匹配用KM算法来做~~不过km是求最大的匹配边权~~所以我们直接将距离取反~~求出结果后输出其相反数就行了~。

#include <iostream>
#include <cstring>
#include <cstdio>
#include<algorithm>
using namespace std;
const int INF = 10000000;
struct ***
{
	int x, y;
}man[105], house[105];
int dis[105][105];
int ex_man[105];
int ex_house[105];
bool vis_man[105];
bool vis_house[105];
int match[105];
int slack[105];
int n, m;
int M_cnt, H_cnt;
void init()
{
	M_cnt = 0;
	H_cnt = 0;
}
int hh(int x)
{
	if (x < 0)
	{
		return -x;
	}
	return x;
}
bool dfs(int man)
{
	vis_man[man] = true;
	for (int house = 0; house < M_cnt; ++house)
	{

		if (vis_house[house]) continue;
		int gap = ex_man[man] + ex_house[house] - dis[man][house];
		if (gap == 0)
		{
			vis_house[house] = true;
			if (match[house] == -1 || dfs(match[house]))
			{
				match[house] = man;
				return true;
			}
		}
		else
		{
			slack[house] = min(slack[house], gap);
		}
	}
	return false;
}
int KM()
{
	memset(match, -1, sizeof match);
	memset(ex_house, 0, sizeof ex_house);
	for (int i = 0; i < M_cnt; ++i)
	{
		ex_man[i] = dis[i][0];
		for (int j = 1; j < M_cnt; ++j)
		{
			ex_man[i] = max(ex_man[i], dis[i][j]);
		}
	}
	for (int i = 0; i < M_cnt; ++i)
	{
		for (int s = 0; s < 101; s++)
		{
			slack[s] = INF;
		}
		while (1)
		{
			memset(vis_man, false, sizeof vis_man);
			memset(vis_house, false, sizeof vis_house);
			if (dfs(i))
			{
				break;
			}
			int d = INF;
			for (int j = 0; j < M_cnt; ++j)
			{
				if (!vis_house[j])
				{
					d = min(d, slack[j]);
				}
			}
			for (int j = 0; j < M_cnt; ++j)
			{
				if (vis_man[j]) ex_man[j] -= d;
				if (vis_house[j]) ex_house[j] += d;
				else slack[j] -= d;
			}
		}
	}
	int res = 0;
	for (int i = 0; i < M_cnt; ++i)
		res += dis[match[i]][i];
	return res;
}
int main()
{
	while (~scanf("%d%d", &n, &m) && n + m)
	{
		init();
		for (int s = 1; s <= n; s++)
		{
			for (int e = 1; e <= m; e++)
			{
				char w;
				cin >> w;
				if (w == 'm')
				{
					man[M_cnt].x = s;
					man[M_cnt++].y = e;
				}
				else if (w == 'H')
				{
					house[H_cnt].x = s;
					house[H_cnt++].y = e;
				}
			}
		}
		for (int s = 0; s < M_cnt; s++)
		{
			for (int e = 0; e < H_cnt; e++)
			{
				dis[s][e] = -(hh(man[s].x - house[e].x) + hh(man[s].y - house[e].y));
			}
		}
		cout << -KM() << endl;
	}
	return 0;
}

全部评论

相关推荐

就前几天旅游的时候,打开抖音就经常刷到这类视频:以前是高学历学生、老师、主持人,现在做着团播、擦边主播的工作,以及那些经过精心包装的“职业转型”故事——从铺天盖地的VLOG到所谓的“04年夜场工作日记”,这些内容在初中升学、高考放榜等关键时间节点持续发酵。可以说非常直接且精准地在潜移默化地影响着心智尚未成熟的青少年,使其对特殊行业逐渐脱敏。那我就想问了:某些传播公司、平台运营者甚至某些夜场的老板,你们究竟在传递怎样的价值观?点开那些视频,评论区里也是呈现明显的两极分化:一种是​​经济下行论​​:“现在就业市场已经艰难到这种程度了吗?”​​一种是事实反驳派​​:这些创作者往往拥有名校背景,从事着...
牛客刘北:被环境教育的,为了能拿到足够的钱养活自己,不甘心也得甘心,现在的短视频传播的思想的确很扭曲,但是很明显,互联网玩上一年你就能全款提A6,但你全心全意不吃不喝工作一年未必能提A6,但是在高考中考出现这个的确很扭曲,在向大家传播“不上学,玩互联网也可以轻松年入百万”,不是人变了,是社会在变
预测一下26届秋招形势
点赞 评论 收藏
分享
白火同学:大二有这水平很牛了,可以适当对关键信息加粗一点,比如关键技术、性能指标之类的。
点赞 评论 收藏
分享
ohs的小木屋:比不少实习待遇高了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务