题目链接:http://poj.org/problem?id=2195

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions:27150   Accepted: 13536

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.
题目大意:人与房子的数量相等,人每走一步花费代价为1,求所有人都进入房子的总代价最小是多少。
思路:
1.可以用KM算法,也可以用最小费用最大流。这里用最大流,KM算法在这里:https://www.cnblogs.com/yuanweidao/p/11282994.html
2.设置一个超级源点0和超级汇点 2 * n + 1, 源点向人加容量为1,费用为0的边,房子向汇点加容量为1,费用用0的边(保证费用来自人到房子的代价)。每个人与每间房子都加容量为1,费用为该人到该房子需要移动的距离与人走路代价的乘积。
(容量都为1保证跑MCMF时每条边都跑到,即每个人都到房子里去了。)
 #include<stdio.h>
#include<string.h>
#include<queue>
#include<math.h>
#include<algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MAXN = + ;
const int inf = 0x3f3f3f3f; char map[MAXN][MAXN];
int cnt1/*人的序号*/, cnt2/*房子的序号*/;
int mincost, last[ * MAXN], pre[ * MAXN], dis[ * MAXN], flow[ * MAXN], vis[ * MAXN];
queue<int> Q; struct Node
{
int x, y;
}no[ * MAXN]; struct Edge
{
int to, next, flow, cost;
}edge[ * MAXN * MAXN];
int head[ * MAXN], e_num;
void add(int a, int b, int c, int d)
{
edge[++ e_num].to = b;
edge[e_num].next = head[a];
head[a] = e_num;
edge[e_num].flow = c;
edge[e_num].cost = d;
} void init()
{
mincost = ;
cnt1 = ;
e_num = -;
mem(head, -);
} bool spfa(int st, int ed)
{
mem(dis, inf), mem(flow, inf), mem(vis, );
pre[ed] = -;
dis[st] = ;
vis[st] = ;
Q.push(st);
while(!Q.empty())
{
int now = Q.front();
Q.pop();
vis[now] = ;
for(int i = head[now]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(edge[i].flow > && dis[to] > dis[now] + edge[i].cost)
{
dis[to] = dis[now] + edge[i].cost;
pre[to] = now;
last[to] = i;
flow[to] = min(flow[now], edge[i].flow);
if(!vis[to])
{
vis[to] = ;
Q.push(to);
}
}
}
}
return pre[ed] != -;
} void MCMF()
{
while(spfa(, cnt2 + ))
{
int ed = cnt2 + ;
int now = ed;
// maxflow += flow[ed];
mincost += flow[ed] * dis[ed];
while(now != )
{
edge[last[now]].flow -= flow[ed];
edge[last[now] ^ ].flow += flow[ed];
now = pre[now];
}
}
} int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
getchar();
init();
if(n == && m == )
break;
for(int i = ; i <= n; i ++)
scanf("%s", map[i] + );
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
if(map[i][j] == 'm')
no[++ cnt1].x = i, no[cnt1].y = j; //人的编号和坐标
cnt2 = cnt1;
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
if(map[i][j] == 'H')
no[++ cnt2].x = i, no[cnt2].y = j;//房子编号和坐标
for(int i = ; i <= cnt1; i ++) //源点 0 到每个人加边 容量为1 花费为0
{
add(, i, , );
add(i, , , );
}
for(int i = cnt1 + ; i <= cnt2; i ++)//房子到 汇点 cnt2 + 1 加边 容量为1 花费为0
{
add(i, cnt2 + , , );
add(cnt2 + , i, , );
}
for(int i = ; i <= cnt1; i ++)
{
for(int j = cnt1 + ; j <= cnt2; j ++)
{
int a, b, c, d;
a = i, b = j, c = ;
d = abs(no[i].x - no[j].x) + abs(no[i].y - no[j].y);//花费为两点之间的哈密顿距离
add(a, b, c, d);
add(b, a, , -d);
}
}
MCMF();
printf("%d\n", mincost);
}
return ;
}

POJ2195

 

POJ 2195 Going Home 【最小费用最大流】的更多相关文章

  1. POJ 2195 - Going Home - [最小费用最大流][MCMF模板]

    题目链接:http://poj.org/problem?id=2195 Time Limit: 1000MS Memory Limit: 65536K Description On a grid ma ...

  2. POJ 2195 Going Home 最小费用最大流 尼玛,心累

    D - Going Home Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Subm ...

  3. poj 2195 Going Home(最小费用最大流)

    题目:http://poj.org/problem?id=2195 有若干个人和若干个房子在一个给定网格中,每人走一个都要一定花费,每个房子只能容纳一人,现要求让所有人进入房子,且总花费最小. 构造一 ...

  4. poj 2351 Farm Tour (最小费用最大流)

    Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17230   Accepted: 6647 Descri ...

  5. POJ 2157 Evacuation Plan [最小费用最大流][消圈算法]

    ---恢复内容开始--- 题意略. 这题在poj直接求最小费用会超时,但是题意也没说要求最优解. 根据线圈定理,如果一个跑完最费用流的残余网络中存在负权环,那么顺着这个负权环跑流量为1那么会得到更小的 ...

  6. poj 2135 Farm Tour 最小费用最大流建图跑最短路

    题目链接 题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边:从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少? 思路 ...

  7. POJ 3680: Intervals【最小费用最大流】

    题目大意:你有N个开区间,每个区间有个重量wi,你要选择一些区间,使得满足:每个点被不超过K个区间覆盖的前提下,重量最大 思路:感觉是很好想的费用流,把每个区间首尾相连,费用为该区间的重量的相反数(由 ...

  8. POJ 2135 Farm Tour [最小费用最大流]

    题意: 有n个点和m条边,让你从1出发到n再从n回到1,不要求所有点都要经过,但是每条边只能走一次.边是无向边. 问最短的行走距离多少. 一开始看这题还没搞费用流,后来搞了搞再回来看,想了想建图不是很 ...

  9. [poj] 1235 Farm Tour || 最小费用最大流

    原题 费用流板子题. 费用流与最大流的区别就是把bfs改为spfa,dfs时把按deep搜索改成按最短路搜索即可 #include<cstdio> #include<queue> ...

  10. POJ 2516 Minimum Cost [最小费用最大流]

    题意略: 思路: 这题比较坑的地方是把每种货物单独建图分开算就ok了. #include<stdio.h> #include<queue> #define MAXN 500 # ...

随机推荐

  1. python--第四天练习题

    #1.写函数,利用递归获取斐波那契数列中的第 10 个数,并将该值返回给调用者. def rec(a,b,dep=1): c = a + b if dep == 10: return c return ...

  2. Jest自动化测试

    最近一直很苦恼,测试这一块的内容,一直想提升测试效率,从慕课网了解到了自动化测试jest ,准备试下下,记录一下学习笔记,方便别人使用 1 什么是 Jest? Jest是 Facebook 的一套开源 ...

  3. 004_FreeRTOS创建与删除任务

    (一)创建与删除任务函数 (二)上面的四个函数目前只用动态创建任务和删除任务 (三)动态创建任务 函数 xTaxkCreate() 1. 宏 configSUPPORT_DYNAMIC_ALLOCAT ...

  4. [POI2015]LAS

    洛谷题目链接 动态规划: 这里用一种我想不到的思想,我们以美食来转移,设计状态$f[i][S](S\in\{0\sim3\})$其中$S$为$0$时表示第$i$个食物没有被人选,$1$表示被左边的人选 ...

  5. 把字符串当做js代码执行的方法

    字符串还能当做javascript代码来执行?你能想到哪些方法? 1.setInterval("要执行的字符串",500);window对象的方法既可以传字符串,也可以传函数.该函 ...

  6. Spring Cloud Eureka(六):Eureka Client 如何注册到Eureka Server

    1.本节概要 根据前文我们对Eureka Server 有了一定的了解,本节我们主要学习Eureka Client 与 Eureka Server 如何通讯的及相关通信机制是什么,本文会弄清楚一下几个 ...

  7. let和const关键字

    一:let 关键字 1.作用: - 与var类似, 用于声明一个变量 2.特点 - 在块作用域内有效 - 不能重复声明 - 不会预处理, 不存在提升 3.应用 - 循环遍历加监听 - 使用let取代v ...

  8. Jenkins系统初始化配置

    1.点击系统管理-->全局安全配置 2.设置允许用户注册,点击保存 3.配置全局工具 4.配置maven文件路径,使用文件系统中的settings文件 5.配置jdk 6.配置maven 7.我 ...

  9. Flask 生成下载文件

    1 后台程序直接生成文件内容 from flask import make_response @app.route('/testdownload', methods=['GET']) def test ...

  10. 一个XP SP3调用0地址蓝屏BUG

    0x00 蓝屏的堆栈 在XP SP3上跑POC之后,一段时间之后会出现蓝屏,蓝屏的堆栈如下,可以看出是ACKData里面CALL了一个0指针导致的蓝屏 0x01 蓝屏原因 1 ETW(Event Tr ...