POJ2195 Going Home

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 22091   Accepted: 11156

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

从每个人向每幢房子连边,边权为行走代价。之后跑最小费用最大流。

看到用最小权二分图匹配也可以解,然而并不会

  1 //#include <bits/stdc++.h>
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<queue>
  7 #include<cstring>
  8 using namespace std;
  9 const int INF=1e8;
 10 const int mxn=240;
 11 int ans;
 12 struct edge{
 13     int cap;
 14     int f,res;
 15     int v;
 16 }e[mxn][mxn];
 17 struct start{
 18     int x,y;
 19 }a[mxn];
 20 struct house{
 21     int x,y;
 22 }h[mxn];
 23 int acnt=0,hcnt=0;
 24 int n,m;
 25 int S,T;
 26 char mp[mxn][mxn];
 27 void init(){
 28     memset(e,0,sizeof e);
 29     acnt=hcnt=0;
 30     ans=0;
 31 }
 32 bool inq[mxn];
 33 int dis[mxn];
 34 int pre[mxn];
 35 void SPFA(int s){
 36     memset(dis,0x3f,sizeof dis);
 37     memset(pre,-1,sizeof pre);
 38     queue<int>q;
 39     q.push(s);
 40     inq[s]=1;
 41     dis[s]=0;
 42     while(!q.empty()){
 43         int u=q.front();q.pop();inq[u]=0;
 44         for(int i=0;i<=T;i++){//v
 45             int v=i;
 46             if(e[u][v].res==0)continue;
 47             if(e[u][v].v==INF) e[u][v].v=-e[v][u].v;
 48             if(dis[v]>dis[u]+e[u][v].v){
 49                 dis[v]=dis[u]+e[u][v].v;
 50                 pre[v]=u;
 51                 if(!inq[v]){
 52                     inq[v]=1;
 53                     q.push(v);
 54                 }
 55             }
 56         }
 57     }
 58     return;
 59 }
 60 int minres=0;
 61 void maxflow(int s,int t){
 62     SPFA(s);
 63     while(pre[t]!=-1){
 64         ans+=dis[t];
 65         int tmp=INF;
 66         int u=pre[t],v=t;
 67         while(u!=-1){
 68             tmp=min(tmp,e[u][v].res);
 69             v=u;u=pre[u];
 70         }
 71         u=pre[t],v=t;
 72         while(u!=-1){
 73             e[u][v].f+=tmp;
 74             e[v][u].f-=tmp;
 75             e[u][v].res-=tmp;
 76             e[v][u].res+=tmp;
 77             v=u;u=pre[u];
 78         }
 79         SPFA(s);
 80     }
 81     return;
 82 }
 83 int main()
 84 {
 85     int i,j;
 86     while(scanf("%d%d",&n,&m) && n && m){
 87         init();
 88         for(i=1;i<=n;i++){
 89             scanf("%s",mp[i]+1);
 90             for(j=1;j<=m;j++){
 91                 if(mp[i][j]==‘H‘){
 92                     h[++hcnt].x=i;
 93                     h[hcnt].y=j;
 94                 }
 95                 if(mp[i][j]==‘m‘){
 96                     a[++acnt].x=i;
 97                     a[acnt].y=j;
 98                 }
 99             }
100         }
101         S=0;T=hcnt+acnt+1;
102         for(i=1;i<=T;i++)
103          for(j=1;j<=T;j++)
104              e[i][j].v=INF;
105         for(i=1;i<=acnt;i++){//人
106             e[S][i].v=0;
107             e[S][i].cap=e[S][i].res=1;
108             for(j=1;j<=hcnt;j++){//房子
109                 int w=abs(h[j].x-a[i].x)+abs(h[j].y-a[i].y);
110                 e[i][acnt+j].v=w;
111                 e[i][acnt+j].cap=1;
112                 e[i][acnt+j].res=1;
113                 e[acnt+j][T].v=0;
114                 e[acnt+j][T].cap=e[acnt+j][T].res=1;
115             }
116         }
117         //
118         maxflow(S,T);
119         printf("%d\n",ans);
120     }
121     return 0;
122 }
时间: 2024-10-12 02:51:33

POJ2195 Going Home的相关文章

最小费用流 poj2195

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17955   Accepted: 9145 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 vertical

POJ-2195 Going Home---KM算法求最小权值匹配(存负边)

题目链接: https://vjudge.net/problem/POJ-2195 题目大意: 给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致.man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man.现在要求所有的man都入住house,求最小费用. 思路: KM算法传送门: 理解篇    运用篇 每个man和house建立带权二分图,曼哈顿距离就是边的值,这里要求最小费用,也就是二分图最小权值匹配,但是KM算法求的是二分图最

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

题目链接:POJ-2195 Going Home 题意 给出$N$行$M$列的网格,'m'表示人,'H'表示房子,且'm'和'H'的数量相同,一个人只能进一间房子,一间房子也只能给一个人进去,人可走上下左右四个方向,现在要让所有人进入房子,求最短路径和. 思路 这是一个二分图带权最小匹配问题,可直接用最小费用最大流求解. 源点向人各连一条容量为1,费用为0的边,每个人向每间房子连容量为1,费用为距离的边,每间房子向汇点连容量为1,费用为0的边,然后跑最小费用最大流即可. 代码实现 #includ

POJ-2195(最小费用最大流+MCMF算法)

Going Home POJ-2195 这题使用的是最小费用流的模板. 建模的时候我的方法出现错误,导致出现WA,根据网上的建图方法没错. 这里的建图方法是每次到相邻点的最大容量为INF,而花费为1,因为花费等于距离.但是需要增加一个源点和一个汇点,然后将每个人和源点相连,每个房子和汇点相连,容量都为1,费用都为0. #include<iostream> #include<algorithm> #include<cstring> #include<queue>

POJ2195 Going Home[费用流|二分图最大权匹配]

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22088   Accepted: 11155 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 vertica

POJ2195(KB11-D 最小费用最大流)

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 23515   Accepted: 11853 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 vertica

POJ-2195

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19680   Accepted: 10003 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 vertica

POJ2195 Going Home【二分图最佳匹配】

题目链接: http://poj.org/problem?id=2195 题目大意: 在一个N*M的矩阵中,有M个人和M个房子,每个人要安排一个房子,每个房子只能安排一个人. 而每个人移动一步需要一美元.那么问题来了:求为每个人安排房子移动所需要的金钱最小值是多 少. 思路: 做一个二分图,一边为人,另一边为房子,如果把人和房子之间的距离作为边权的话,问题就变成 了求带权二分图最小权和的最佳匹配.这里我们为了方便计算,吧人和房子之间的距离的负值作为 边权,那么就变成了求带权二分图最大权和的最佳匹

POJ2195:Going Home(费用流入门)

http://poj.org/problem?id=2195 #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <queue> #include <math.h> #define inf 0x3f3f3f3f using namespace std; struct node1//记录h或者m的坐标 { int