Going Home
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 20115   Accepted: 10189

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

题解:这个题意就是,m个人都进入不同的房子的步数和最小;那么求负的步数的最大匹配就可以了;km算法;

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mem(x,y) memset(x,y,sizeof(x))
const int MAXN=;
const int INF=1e4;
char s[MAXN][MAXN];
int mp[MAXN][MAXN],lx[MAXN],ly[MAXN],usdx[MAXN],usdy[MAXN],mat[MAXN];
struct Node{
int x,y;
}hou[MAXN],man[MAXN];
int k;
bool dfs(int x){
usdx[x]=;
for(int i=;i<=k;i++){
if(!usdy[i]&&lx[x]+ly[i]==mp[x][i]){
usdy[i]=;
if(!mat[i]||dfs(mat[i])){
mat[i]=x;return true;
}
}
}
return false;
}
int km(){
mem(mat,);mem(lx,);mem(ly,);
for(int i=;i<=k;i++)
for(int j=;j<=k;j++)
lx[i]=max(lx[i],mp[i][j]);
for(int i=;i<=k;i++){
mem(usdx,);mem(usdy,);
while(!dfs(i)){
int d=INF;
for(int j=;j<=k;j++)
if(usdx[j])
for(int b=;b<=k;b++)
if(!usdy[b])
d=min(d,lx[j]+ly[b]-mp[j][b]);
for(int j=;j<=k;j++){
if(usdx[j])lx[j]-=d;
if(usdy[j])ly[j]+=d;
}
mem(usdx,);mem(usdy,);
}
}int ans=;
for(int i=;i<=k;i++)ans+=lx[i]+ly[i];
return INF*k-ans;
}
int main(){
int N,M;
while(scanf("%d%d",&N,&M),N|M){
int k1=,k2=;
for(int i=;i<N;i++){
scanf("%s",s[i]);
for(int j=;j<M;j++){
if(s[i][j]=='H')hou[++k1].x=i,hou[k1].y=j;
if(s[i][j]=='m')man[++k2].x=i,man[k2].y=j;
}
}k=k1;
// printf("%d %d\n",k1,k2);
for(int i=;i<=k;i++)
for(int j=;j<=k;j++)
mp[i][j]=INF-(abs(hou[i].x-man[j].x)+abs(hou[i].y-man[j].y));//这样是因为要找最小的距离,所以把距离变成负的+INF找最大匹配就行了;
printf("%d\n",km());
}
return ;
}

Going Home(最大匹配km算法)的更多相关文章

  1. 带权二分图最大匹配KM算法

    二分图的判定 如果一个图是连通的,可以用如下的染色法判定是否二分图: 我们把X部的结点颜色设为0,Y部的颜色设为1. 从某个未染色的结点u开始,做BFS或者DFS .把u染为0,枚举u的儿子v.如果v ...

  2. UVA1349(带权二分图最大匹配 --> KM算法模板)

    UVA1349 题意:给定一些有向带权边,求出把这些边构造成一个个环,总权值最小 解法: 对于带权的二分图的匹配问题可以用通过KM算法求解. 要求最大权匹配就是初始化g[i][j]为0,直接跑就可以: ...

  3. 二分图的最大匹配以及带权匹配【匈牙利算法+KM算法】

    二分图算法包括 匈牙利算法 与 KM算法. 匈牙利算法 在这里写上模板. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063 #include< ...

  4. 浅谈二分图的最大匹配和二分图的KM算法

    二分图还可以,但是我不太精通.我感觉这是一个很烦的问题但是学网络流不得不学它.硬啃吧. 人比较蠢,所以思考几天才有如下理解.希望能说服我或者说服你. 二分图的判定不再赘述一个图是可被划分成一个二分图当 ...

  5. 二分图 最大权匹配 km算法

    这个算法的本质还是不断的找增广路: KM算法的正确性基于以下定理:若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最 ...

  6. Ural1076(km算法)

    题目大意 给出n*n表格,第a[i,j]表示i到j的权值,现在我们要将每个a[i,j]=sum[j]-a[i,j], 求出当前二分图a[][]最小匹配 最小匹配只需将权值取负后,求二分图最大匹配,使用 ...

  7. km算法的个人理解

    首先相对于上个blog讲的匈牙利算法用于解决无权二分图的最佳匹配,km算法则是在匈牙利算法基础上更进一层的,每条边增加了权值后,真的开始看时有些无厘头,觉得没有什么好方法,但两位牛人Kuhn-Munk ...

  8. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  9. KM算法专题

    原文:http://972169909-qq-com.iteye.com/blog/1184514 题目地址:这里. 1)求图中所有环的总长度(环的长度不唯一)的最小值.当无法得到完备匹配时说明环不存 ...

随机推荐

  1. HTTP请求和数据安全

    /*------------------------------------- 01 HTTP请求 ---------------------------------------*/ 重点:1.超文本 ...

  2. 5.5 Function类型

    说起来ECMAScript中上面最有意思,我想那莫过于函数了,有意思的根源,则在于函数实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此 ...

  3. 关于jq操作table下多个type=radio的input的选中

    假如有2个table: <table id="table1" border="0"> <tr> <td><input ...

  4. w2wp.exe 已附加有调试器,但没有将该调试器配置为调试此未经处理的异常

    一.问题描述 昨天系统联调,用到了VS2010 附件进程,把w2wp.exe 进程添加到vs2010 的调试进程中,这样其他系统访问我们系统,就可以捕获断点进行调试 但是,今天F5 调试的时候,发现直 ...

  5. codeforces 622C. Optimal Number Permutation 构造

    题目链接 假设始终可以找到一种状态使得值为0, 那么两个1之间需要隔n-2个数, 两个2之间需要隔n-3个数, 两个3之间隔n-4个数. 我们发现两个三可以放到两个1之间, 同理两个5放到两个3之间. ...

  6. Python一些字符串判断和转换

    设s是字符串: s.isalnum()      判断所有字符都是数字或者字母 s.isalpha()  判断所有字符都是字母 s.isdigit()  判断所有字符都是数字 s.islower() ...

  7. iter, yield与enumerate的实现

    模拟实现一个enumerate函数 def myEnumerate(seq, start=0): results = [] n = start for i in seq: results.append ...

  8. FreeBSD 10安装KDE桌面环境简介(亲测bsdconfig命令有效)

    FreeBSD 10出来一段时间了,自己摸索装上KDE环境,网上介绍的都是10以前版本的,要么对现在的不合适,走了一大圈弯路还是装不好:要么太繁琐且装了一堆无用的软件.本着让更多人能快速方面的入门Fr ...

  9. 细说SSO单点登录(转)

    什么是SSO? 如果你已知道,请略过本节! SSO核心意义就一句话:一处登录,处处登录:一处注销,处处注销.即:在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 很多人容易把SS ...

  10. Python的MySQLdb模块安装,连接,操作,增删改

    1. 首先确认python的版本为2.3.4以上,如果不是需要升级python的版本     python -V   检查python版本 2. 安装mysql, 比如安装在/usr/local/my ...