hdu 2732 Leapin' Lizards(最大流)Mid-Central USA 2005
废话:
这道题不难,稍微构造一下图就可以套最大流的模板了。但是我还是花了好久才解决。一方面是最近确实非常没状态(托词,其实就是最近特别颓废,整天玩游戏看小说,没法静下心来学习),另一方面是不够细心,输出格式错了大意没有发现死一只和死多只之间的区别,卡在那里动不了。
题意:
在一张n*m的地图中,有一群蜥蜴,这群蜥蜴每次可以跳跃曼哈顿距离d(曼哈顿距离——dis(a, b) = |ax-bx|+|ay-by|,之后所有的距离都是曼哈顿距离),这些蜥蜴只能在地图上的一些柱子上跳跃。柱子i最多可以支持ki次经过。如果柱子i距离地图的边界的距离小于d那么蜥蜴可以从柱子i逃出升天。要求计算最后会有多少蜥蜴葬身图中。
输入:
第一行输入一个整数t,表示共有t组数据。
第二行输入两个整数n,d,表示这组数据中地图有n行,蜥蜴一次最大跳跃距离d。
接下来n行输入地图mp1,地图中的数字表示柱子可以经过的次数,0表示不可以经过。
接下来n行输入地图mp2,其中’.’表示空,’L’表示存在一只蜥蜴。
输出:
首先输出组数”Case #x: “,其中x表示第x组。
如果所有的蜥蜴都可以逃出,那么输出”no lizard was left behind.”
如果只有1只死去,那么输出”1 lizard was left behind.”
如果死去多于1只,那么输出”y lizards were left behind.”y表示死去的蜥蜴数量。
题解:
经过一番变化,我们可以构造出一张有向图,然后使用最大流来解决这个问题。
构造方法如下——
- 我们设源点为0,汇点为2*n*m+1(其中n为地图的行,m为地图的列),设图中两点p1到p2的距离,即p1到p2的有向边为mp[p1][p2]。
- 将地图mp1中所有的点拆分成两个点,点pij拆分为mp[][]中的点i*m+j+1与n*m+i*m+j+1,添加边mp[i*m+j+1][n*m+i*m+j+1] = mp1[i][j]。这是我们构造图mp中最关键的一步,正是因为有了这个有向边,我们才可以使用最大流来计算这个题。
- 对于地图mp1,枚举每个点pij,如果这个点距离地图边界的距离小于等于d,那么添加边mp[n*m+i*m+j+1][2*m*n+1] = mp1[i][j];同时枚举除pij以外的点pkl,如果pij与pkl之间的距离小于等于d那么添加边mp[n*m+i*m+j+1][k*m+l+1] = max(mp1[i][j], mp1[k][l])。
- 对于地图mp2,如果某个点pij 的值mp2[i][j] == ‘L’,那么构造边mp[0][i*m+j+1] = 1。
然后计算从源点到汇点的最大流即可,我使用的Dinic算法。
具体见代码——
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std; const int N = ;
const int M = ; int dis[N];
int cur[N];
bool vis[N];
char mp[][][];
int mp2[N][N];
int n, m, d, t;
int ans, sum; inline int Min(int x, int y)
{
return x < y ? x : y;
} void init()
{
memset(mp, , sizeof(mp));
memset(mp2, , sizeof(mp2));
scanf("%d%d", &n, &d);
scanf("%s", mp[][]);
m = strlen(mp[][]);
sum = ;
ans = ;
for(int i = ; i < n; i++)
{
scanf("%s", mp[][i]);
}
for(int i = ; i < n; i++)
{
for(int j = ; j < m; j++)
{
for(int k = ; k < n; k++)
{
for(int l = ; l < m; l++)
{
int mid1 = abs(i-k)+abs(j-l);
if(mid1 <= d && i*m+j+ != k*m+l+) //点pij到点pkl之间距离小于等于d且不是同一点
{
int mid = Min(mp[][i][j], mp[][k][l]);
mp2[n*m+i*m+j+][k*m+l+] = mid; //从点pij到点pkl的边
}
}
}
mp2[i*m+j+][n*m+i*m+j+] = mp[][i][j]-''; //从点pij到点pij的边
if(i < d || j < d || n-i <= d || m-j <= d) mp2[m*n+i*m+j+][*n*m+] = mp[][i][j]-''; //从点pij到汇点的边
}
}
for(int i = ; i < n; i++)
{
scanf("%s", mp[][i]);
for(int j = ; j < m; j++)
{
if(mp[][i][j] == 'L')
{
mp2[][i*m+j+] = ; //从源点到点pij的边
sum++;
}
}
}
m = *n*m+;
} bool bfs()
{
memset(vis, , sizeof(vis));
queue<int> que;
que.push();
dis[] = ;
vis[] = ;
while(!que.empty())
{
int k = que.front();
que.pop();
for(int i = ; i <= m; i++)
{
if(!vis[i] && mp2[k][i] > )
{
vis[i] = ;
dis[i] = dis[k]+;
que.push(i);
}
}
}
return vis[m];
} int dfs(int x, int val)
{
if(x == m || val == ) return val;
int flow = , minn;
for(int& i = cur[x]; i <= m; i++)
{
if(dis[x]+ == dis[i] && (minn = dfs(i, Min(val, mp2[x][i]))) > )
{
mp2[x][i] -= minn;
mp2[i][x] += minn;
flow += minn;
val -= minn;
if(val == ) break;
}
}
return flow;
} void work() //Dinic算法
{
while(bfs())
{
for(int i = ; i <= m; i++) cur[i] = ;
ans += dfs(, M);
}
} void outit(int tm)
{
sum -= ans;
printf("Case #%d: ", tm);
if(!sum) printf("no lizard was left behind.\n");
else if(sum == ) printf("1 lizard was left behind.\n");
else printf("%d lizards were left behind.\n", sum);
} int main()
{
//freopen("test.in", "r", stdin);
scanf("%d", &t);
for(int tm = ; tm <= t; tm++)
{
init();
work();
outit(tm);
}
return ;
}
最大流入门——
http://www.cnblogs.com/mypride/p/4859453.html
hdu 2732 Leapin' Lizards(最大流)Mid-Central USA 2005的更多相关文章
- hdu 2732 Leapin' Lizards 最大流 拆点 建图
题目链接 题意 给定一张网格,格子中有些地方有柱子,有些柱子上面有蜥蜴. 每个柱子只能承受有限只蜥蜴从上面经过.每只蜥蜴每次能走到相距曼哈顿距离\(\leq k\)的格子中去. 问有多少只蜥蜴能走出网 ...
- hdu 2732 Leapin' Lizards (最大流 拆点建图)
Problem Description Your platoon of wandering lizards has entered a strange room in the labyrinth yo ...
- POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流)
POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流) Description Yo ...
- HDU 2732 Leapin' Lizards(最大流)
http://acm.hdu.edu.cn/showproblem.php?pid=2732 题意: 给出n行的网格,还有若干只蜥蜴,每只蜥蜴一开始就在一个格子之中,并且给出蜥蜴每次的最大跳跃长度d. ...
- HDU - 2732 Leapin' Lizards (拆点最大流)
题意:有N*M的矩形,每个格点有一个柱子,每根柱子有高度c,允许蜥蜴经过这根柱子c次,开始有一些蜥蜴在某些柱子上,它们要跳出这个矩形,每步最大能跳d个单位,求最少有多少蜥蜴不能跳出这个矩形. 分析:转 ...
- HDU 2732 Leapin' Lizards
网络最大流+拆点.输出有坑!!! #include<cstdio> #include<cstring> #include<string> #include<c ...
- HDU 2732 Leapin' Lizards(拆点+最大流)
HDU 2732 Leapin' Lizards 题目链接 题意:有一些蜥蜴在一个迷宫里面,有一个跳跃力表示能跳到多远的柱子,然后每根柱子最多被跳一定次数,求这些蜥蜴还有多少是不管怎样都逃不出来的. ...
- HDU2732 Leapin' Lizards —— 最大流、拆点
题目链接:https://vjudge.net/problem/HDU-2732 Leapin' Lizards Time Limit: 2000/1000 MS (Java/Others) M ...
- Leapin' Lizards [HDU - 2732]【网络流最大流】
题目链接 网络流直接最大流就是了,只是要拆点小心一个点的流超出了原本的正常范围才是. #include <iostream> #include <cstdio> #includ ...
随机推荐
- 【转】java线程系列---Runnable和Thread的区别
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...
- 自绘CProgressCtrl进度条控件,支持自定义显示文本和进程百分比信息
// CXProgressCtrl 头文件 #pragma once // CXProgressCtrl class CXProgressCtrl : public CProgressCtrl { D ...
- oracle11g 修改字符集 修改为ZHS16GBK
1.cmd下,cd到oracle数据库软件的服务器端 如:D:\app\Administrator\product\11.2.0\dbhome_1\BIN 2.输入set ORACLE_SID=你想进 ...
- Eclipse中使用正则表达式搜索替换
Eclipse中使用正则表达式搜索替换 分类:software | 标签: 正则表达 替换 eclipse 2011-11-29 11:28 阅读(1930)评论(0)编辑删除 最近在eclip ...
- highCharts图表入门实例
本文通过讲解Highcharts生成一个简单的3D柱状图实例来学习Highcharts的使用. JSP 页面 1.需要引入的js文件 <script src="<%=basePa ...
- jstl long类型数据转换为日期格式
一.有WEB-INF下建立一个datetag.tld <?xml version="1.0" encoding="UTF-8"?> <tagl ...
- linux 配置 wlan 连接
第一步,先确定你已经安装了无线网卡驱动.我的是 ath9k ,linux 内核不自带,现编译成模块 然后安装上.具体步骤请自行搜索 linux 编译内核 第二步,起用模块 modprobe ath9k ...
- 使用ExtJs实现文件下载
文件下载,是不可以直接通过Ext.Ajax.Request来实现的.一般的,可以通过创建一个隐藏的form表单来实现.具体代码以及代码注释如下: if (!Ext.fly('downForm')){ ...
- 如何使用 EXCEL 的筛选功能
假设有一个Excel文档,有两列“姓名”和“成绩”. 现需筛选出成绩 “大于等于90”或者“小于60”的学生. 步骤如下: 1.选中任意一个单元格,点击工具栏上的 数据 - 筛选 - 自动筛选 ,可以 ...
- Ubuntu 12.04 LTS(64bit) 环境下JDK、 Eclipse、 ADT、 快捷图标
一.在FriendlyARM,Tiny4412,,安装包下可补充: (按照手册添加openjdk-6-jdk 后) 安装JDK (Java),选择需要的JDK,或者全部安装. a) OpenJDK-6 ...