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的升级版. 题目大概是 ...
随机推荐
- Java中的方法应用
一.如何定义java中的方法 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 语法: 1. 访问修饰符:方法允许被访问的权限范围, 可以是 public.protected.priv ...
- java 的 sqlHelper,改改之后也适用于不使用 EF 的 C# 项目,包含查询和建表。
这个类用来拼接 sql. package com.ly.orm; public class Query { protected Query(String v) { sql = v; } public ...
- php 使用curl模拟登录discuz以及模拟发帖
<?php$discuz_url = 'http://127.0.0.1/discuz/';//论坛地址$login_url = $discuz_url .'logging.php?action ...
- Android 三级联动选择城市+后台服务加载数据库
技术渣,大家将就着看 首先我们需要一个xml数据保存到数据库,这里我从QQ下面找到一个loclist.xml文件 <CountryRegion Name="中国" Code= ...
- jmeter 内存溢出解决方法
执行“评论新鲜事”200并发就内存溢出 解决方法: [caozijuan@test09 bin]$ vi jmeter JVM_ARGS="-Xms1024m -Xmx4096m" ...
- Calculator(补)
MyGitHub 刚刚开始时确实是连题目都看不懂= =,从第二行的新建类开始,就不知题目所云.所以我的困难比很多同学都要 开始得早一些--从题目第二行开始. 准确的说,当我按照题目要求新建了一个sca ...
- 程设大作业xjb写——魔方复原
鸽了那么久总算期中过[爆]去[炸]了...该是时候写写大作业了 [总不能丢给他们不会写的来做吧 一.三阶魔方的几个基本定义 ↑就像这样,可以定义面的称呼:上U下D左L右R前F后B UD之间的叫E,LR ...
- composer 一些使用说明
1 使用订制的包 配置 "repositories": [ { "type": "path", "url": " ...
- 控件包含代码块(即 <% ... %>),因此无法修改控件集合
错误: “/”应用程序中的服务器错误. 控件包含代码块(即 <% ... %>),因此无法修改控件集合. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解 ...
- MYSQL获取自增ID的四种方法
MYSQL获取自增ID的四种方法 1. select max(id) from tablename 2.SELECT LAST_INSERT_ID() 函数 LAST_INSERT_ID 是与tabl ...