PKu 2195
//PKu 2195 回家 By Loli_con Enail : Loli_con@outlook.com
/*
题目叙述
=========
在一个网格图中,有n个人和n个房子。每一个单位时间,每个小人可以移动一个单位长度,无论水平还是竖直,到临近的点。对于每个人,每移动一步你需要花费1$,直到他移动到他的家,题目限制一个房子仅能住进一个人
你的任务是计算最小花费使得n个人都能住进不同的n个房子。
输入是一张地图,'.'表示空地,'H'表示房子,'m'表示人
你可以认为一个点是足够的大以至于可以同时站上去全部的n个人,当然,一个人也可以站在房子那个点而不进入。
=====================
输入叙述
=====================
多组测试数据。对于每组测试数据
第一行包括两个整数n和m,表示地图是n行m列的。
接下来n行每行m个字符,'.'、'H'、'm'含义如上。2<=n,m<=100,H<=100,
输入数据以0 0结束
=====================
输出叙述
=====================
对于每组测试数据输出一行一个整数最小花费
=====================
样例输入
=====================
2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0
=====================
样例输出
=====================
2
10
28
=====================
解题报告
=====================
最小费用最大流模版题,KM算法也可解
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#define Max 5005
#define inf 1<<28
using namespace std;
struct kdq
{
int x,y;
}human[Max],house[Max];
int n,m;
int S,T;//源点,汇点
int cost[Max/][Max];//花费
int cap[Max/][Max];//容量
int dis[Max];
int path[Max];
bool visit[Max];
int q[Max*]; int spfa()//最短路
{
int i,j;
for(i=;i<=T;i++)
dis[i]=inf,path[i]=-,visit[i]=;
dis[S]=;
visit[S]=;
int num=,cnt=;
q[num++]=S;
while(num>cnt)
{
int temp=q[cnt++];
visit[temp]=;
for(i=;i<=T;i++)
{
if(cap[temp][i]&&dis[temp]+cost[temp][i]<dis[i])
{
path[i]=temp;
dis[i]=dis[temp]+cost[temp][i];
if(!visit[i])
{
q[num++]=i;
visit[i]=;
}
}
}
}
return dis[T]!=inf;
} int minCost=;
void getMaxFlow()//增广找最大流
{
int maxFlow=inf; while(spfa())
{
int pre=T;
while(path[pre]!=-)
{
maxFlow=min(maxFlow,cap[path[pre]][pre]);
pre=path[pre];
}
pre=T;
minCost+=dis[T]*maxFlow;//最小费用
while(path[pre]!=-)//更新流
{
cap[path[pre]][pre]-=maxFlow;
cap[pre][path[pre]]+=maxFlow;
//minCost+=cost[path[pre]][pre]*maxFlow;
pre=path[pre];
}
}
cout<<minCost<<endl;
return ;
} int getdis(kdq x,kdq y)//两个坐标之间的费用
{
return (abs(x.x-y.x)+abs(y.y-x.y));
}
void build_map(int numm,int numh)//建图
{
int i,j;
for(i=;i<=numm;i++)//计算房子和人之间的费用
for(j=;j<=numh;j++){
cost[i][j+numm]=getdis(human[i],house[j]);
cost[j+numm][i]=-cost[i][j+numm];//负费用用来回流
}
for(i=;i<=numm;i++)//源点到每个人的cap,cost
cap[S][i]=,cost[S][i]=;
for(i=;i<=numh;i++)//房子到汇点的cap,cost
cap[i+numm][T]=;
for(i=;i<=numm;i++)//每个人和房子之间的cap
for(j=;j<=numh;j++)
cap[i][j+numm]=;
}
int main()
{
int i,j,k,l;
char x;
while(scanf("%d%d",&n,&m),(n+m))
{
memset(cap,,sizeof(cap));
memset(cost,,sizeof(cost)); int numm=,numh=;
for(i=;i<=n;i++)
for(j=;j<=m;j++)
{
cin>>x;
if(x=='m'){
human[++numm].x=i;
human[numm].y=j;
}
if(x=='H'){
house[++numh].x=i;
house[numh].y=j;
}
}
S=;
minCost=;
T=numm+numh+;//其实numm==numh。。。。
build_map(numm,numh);
getMaxFlow();
}
return ;
}
PKu 2195的更多相关文章
- 二分图匹配之KM求二分图最佳匹配算法
参考网址:http://blog.163.com/suntroop@yeah/blog/static/17012103120115185927194/ 对于具有二部划分( V1, V2 )的加权完全二 ...
- HDU——PKU题目分类
HDU 模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 ...
- 刘汝佳黑书 pku等oj题目
原文地址:刘汝佳黑书 pku等oj题目[转]作者:小博博Mr 一.动态规划参考资料:刘汝佳<算法艺术与信息学竞赛><算法导论> 推荐题目:http://acm.pku.edu. ...
- POJ 2195 Going Home 最小费用最大流 尼玛,心累
D - Going Home Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Subm ...
- POJ 2195:Going Home(最小费用最大流)
http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大 ...
- poj 2195 KM算法
题目链接:http://poj.org/problem?id=2195 KM算法模板~ 代码如下: #include "stdio.h" #include "string ...
- poj 2195 二分图带权匹配+最小费用最大流
题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...
- Poj(2195),最小费用流,SPFA
题目链接:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submi ...
- 【解题报告】PKU 2318 TOYS AND PKU 2398 Toy Storage
题目连接: http://poj.org/problem?id=2318 http://poj.org/problem?id=2398 两题类似的题目,2398是2318的升级版. 题目大概是 ...
随机推荐
- CProgressCtrl进度条
CProgressCtrl进度条 使用方法总结 标签: CProgressCtrlmfc 2016-03-03 09:19 762人阅读 评论(0) 收藏 举报 分类: MFC(11) 版权声明: ...
- 使用dreamweaver去掉文本中的空格和换行
当我们从其他地方拷贝文本到网页,在html代码中会自动带有空格和换行,手动去掉很麻烦,今天试着用dreamweaver去了一下,方法如下: 1.点击Ctrl+F,打开“查找和替换”窗口 2‘见下图:
- 关于display:inline-block和float:left的区别
<div class="pag"> <a href="#">首页</a> <a href="#"& ...
- ios基础篇(二十九)—— 多线程(Thread、Cocoa operations和GCD)
一.进程与线程 1.进程 进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内: 如果我们把CPU比作一个工厂,那么进程就好比工厂的车间,一个工厂有 ...
- 在 Xcode 7 中安装 Alcatraz
http://www.jianshu.com/p/5c8ed25ad434 安装Xcode7后,继续采用官方方法安装Alcatraz,发现不成功.单独安装XVim也不成功.看了一下Alcatraz的i ...
- python 获取脚本所在目录
平时写python经常会想获得脚本所在的目录,例如有个文件跟脚本文件放在一个相对的目录位置,那就可以通过脚本文件的目录找到对应的文件,即使以后脚本文件移到其他地方,脚本也基本不需要改动(相对于写死目录 ...
- jdbc escape
假如有这样1个查询请求,模糊查询标题中包含a%b_cc’d的记录,正确的sql应该是下面这样的: select * from t_sch_work_info t where t.title ...
- C#中IQueryable和IEnumberable的区别
IQueryable和IEnumberable的区别主要在查询方面有区别 IQueryable查询时间是先把skip和Take翻译成sql语句,去数据库执行完成后把数据加载到内存中 IEnumbera ...
- int->string-------------c
void intToString(int n,char a[]){ int i=1,m=n; while((n/=10)!=0) i++; int j=0; for(;j<i;j++){ a ...
- PhantomJS linux系统下安装步骤及使用方法(网页截屏功能)
PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API.它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处理, CSS 选择器, JSON, ...