P2472 [SCOI2007]蜥蜴

题目背景

07四川省选

题目描述

在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。

每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

输入输出格式

输入格式:

输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

输出格式:

输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。


解决这题的关键是理解这句话:石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失

我们把这句话转换一下,每个石柱 \(i\) 可以用石柱高度 \(hi\) 次。这是一个限制条件:使用次数,所以我们想到了最大流。

不能逃脱的蜥蜴数即为总蜥蜴数 - 逃脱的蜥蜴数,所以我们现在思考怎么建图

建模

最大流的核心在于限制

由限制条件,对网络流模型极其敏感我们可知道:石柱一定是要拆成两个点的,两点之间边容量为石柱高度 \(h\) ,这样可以限制一个石柱只能跳 \(h\) 次

由最大流答案不可能大于蜥蜴总数,所以我们可以联想到由汇点向蜥蜴所在的石柱连边,容量为 1

由石柱之间在规定距离内可以相互到达,傻子都会我们可以在距离内的石柱连一条容量为INF的边

由要跳出去可得:在跳到外围距离小于d的石柱连一条容量为INF的边

注意:因为每次都要消耗石柱高度,所以连入石柱的边连 石柱1 ,连出石柱的边从 石柱2 出发,从而达到路过石柱消耗高度这一限制

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int RD(){
int out = 0,flag = 1;char c = getchar();
while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
return flag * out;
}
const int maxn = 100019,INF = 1e9;
int num,nume = 1,tot;
int lenx,leny,d;
int map[190][190];
int L[190][190];
int s,t,maxflow;
int head[maxn];
struct Node{
int v,dis,nxt;
}E[maxn << 2];
void add(int u,int v,int dis){
E[++nume].nxt = head[u];
E[nume].v = v;
E[nume].dis = dis;
head[u] = nume;
}
int lev[maxn];
bool bfs(){
queue<int>Q;
memset(lev,0,sizeof(lev));
Q.push(s);
lev[s] = 1;
while(!Q.empty()){
int u = Q.front();
Q.pop();
for(int i = head[u];i;i = E[i].nxt){
int v = E[i].v;
if(E[i].dis && !lev[v]){
lev[v] = lev[u] + 1;
Q.push(v);
if(v == t)return 1;
}
}
}
return 0;
}
int Dinic(int u,int flow){
if(u == t)return flow;
int rest = flow,k;
for(int i = head[u];i;i = E[i].nxt){
int v = E[i].v;
if(E[i].dis && lev[v] == lev[u] + 1 && rest){
k = Dinic(v,min(rest,E[i].dis));
if(!k)lev[v] = 0;
E[i].dis -= k;
E[i ^ 1].dis += k;
rest -= k;
} }
return flow - rest;
}
double getdis(int x1,int y1,int x2,int y2){
return ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
int getindex(int x,int y){
return (x - 1) * leny + y;
}
int main(){
lenx = RD();leny = RD();d = RD();
char temp;
for(int i = 1;i <= lenx;i++){
for(int j = 1;j <= leny;j++){
cin>>temp;
map[i][j] = temp - '0';
}
}
for(int i = 1;i <= lenx;i++){
for(int j = 1;j <= leny;j++){
cin>>temp;
if(temp == 'L'){
L[i][j] = 1;
num++;
}
}
}
//石头1部从1到tot(lenx * leny),2部 + tot,石头编号为(i - 1) * leny + j
tot = lenx * leny;
s = tot * 2 + 1,t = s + 1;
for(int i = 1;i <= lenx;i++){
for(int j = 1;j <= leny;j++){
int I = getindex(i,j);
if(map[i][j]){
add(I,I + tot,map[i][j]);
add(I + tot,I,0);
if(i + d > lenx || i - d < 1 || j + d > leny || j - d < 1){
add(I + tot,t,INF);
add(t,I + tot,INF);
}
if(L[i][j]){
add(s,I,1);
add(I,s,0);
}
}
}
}
for(int x1 = 1;x1 <= lenx;x1++){
for(int y1 = 1;y1 <= leny;y1++){
for(int x2 = 1;x2 <= lenx;x2++){
for(int y2 = 1;y2 <= leny;y2++){
if(getdis(x1,y1,x2,y2) <= d * d){
int u = getindex(x1,y1),v = getindex(x2,y2);
add(u + tot,v,INF);
add(v,u + tot,0);
add(v + tot,u,INF);
add(u,v + tot,0);
}
}
}
}
}
int flow = 0;
while(bfs())while(flow = Dinic(s,INF))maxflow += flow;
printf("%d\n",num - maxflow);
return 0;
}

题解 P2472 【[SCOI2007]蜥蜴】的更多相关文章

  1. P2472 [SCOI2007]蜥蜴(网络流)

    P2472 [SCOI2007]蜥蜴 把每个点拆成2个点,两点之间连边的边权为石柱高度 新建虚拟源点$S$和汇点$T$ $S$向所有有蜥蜴的点连边,边权1 其他边都连$inf$ 剩下就是裸的$dini ...

  2. P2472 [SCOI2007]蜥蜴(网络最大流)

    P2472 [SCOI2007]蜥蜴 题目描述 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距 ...

  3. P2472 [SCOI2007]蜥蜴 (最大流)

    题目 P2472 [SCOI2007]蜥蜴 解析 这个题思路比较清晰,本(qi)来(shi)以(jiu)为(shi)无脑建图跑最大流,结果挂了,整了一个小时后重新建图才过的. 建立一个超级源点和一个超 ...

  4. P2472 [SCOI2007]蜥蜴(最大流)

    P2472 [SCOI2007]蜥蜴 自己第一道独立做题且一遍AC的网络流题纪念... 看到这道题我就想到网络流建图的方式了... 首先根据每个高度,我们将每个点拆成两个点限流.之后根据跳的最大距离, ...

  5. 洛谷P2472 [SCOI2007]蜥蜴 题解

    题目链接: https://www.luogu.org/problemnew/show/P2472 分析: 这道题用最大流解决. 首先构建模型. 一根柱子可以跳入和跳出,于是拆成两个点:入点和出点. ...

  6. 【题解】Luogu P2472 [SCOI2007]蜥蜴

    原题传送门 题目要求无法逃离的最少有多少 直接做肯定不好做,我们帮题目变一个说法:最多能逃离多少 这个询问一看就是最大流 考虑如何建图: 1.将S和每一个有蜥蜴的点连一条流量为1的边(每个蜥蜴只能用1 ...

  7. P2472 [SCOI2007]蜥蜴

    传送门 求无法逃离的蜥蜴总数的最小值就是求最多逃离的蜥蜴总数 所以显然考虑最大流,一个流量的路径就相当于一只蜥蜴逃离的路径 发现每个位置有一个最大经过次数,所以把每个位置拆成两个点$x,y$,$x$ ...

  8. [洛谷P2472] [SCOI2007]蜥蜴

    题目链接: 蜥蜴 题目分析: 一道网络流,先来分析一下问题: 在一个\(r*c\)的图中分布了一些数,其他地方都用\(0\)填充,我们分别从指定的一些数出发,每次可以移动到周围距离为\(d\)以内的数 ...

  9. [BZOJ1066][luogu_P2472][SCOI2007]蜥蜴

    [BZOJ1066][luogu_P2472][SCOI2007]蜥蜴 试题描述 在一个 \(r\) 行 \(c\) 列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥 ...

随机推荐

  1. HTML5+Bootstrap 学习笔记 3

    HTML5 aria-* and role aria是指Accessible Rich Internet Application.role的作用是描述一个非标准的tag的实际作用,而aria-*的作用 ...

  2. 4.hive的外部表和内部表

    1.外部表和内部表区别 创建表时:创建内部表时,会将数据移动到数据仓库指向的路径:若创建外部表,仅记录数据所在的路径, 不对数据的位置做任何改变. 删除表时:在删除表的时候,内部表的元数据和数据会被一 ...

  3. Scrum立会报告+燃尽图(十月十日总第一次):选题

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2190 Scrum立会master:付佳 一.小组介绍 组长:付佳 组员: ...

  4. Scrum立会报告+燃尽图 01

    此作业要求:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2190] 一.小组介绍 组长:王一可 组员:范靖旋,王硕,赵佳璐,范洪达,祁 ...

  5. Right-BICEP 测试四则运算程序

    测试方法:      Right-BICEP 测试计划: 1.边界测试是否正确 2.负数表示是否实现 3.是否有乘除法 4.是否可以选择题目数量 5.是否有输出方式 6.是否有括号 7.是否有重复查询 ...

  6. CSS3:不可思议的border属性

    在CSS中,其border属性有很多的规则.对于一些事物,例如三角形或者其它的图像,我们仍然使用图片代替.但是现在就不需要了,我们可以用CSS形成一些基本图形,我分享了一些关于这方面的技巧. 1.正三 ...

  7. 使用cookie保存用户登录信息

    写入Cookie HttpCookie _cookie = new HttpCookie("User"); _cookie.Values.Add("UserName&qu ...

  8. EL语法 ${person.id} 这里面的id指的是实例对象的成员变量

    EL语法 ${person.id} 这里面的id指的是实例对象的成员变量

  9. solr服务器的查询过程

    SolrDispatchFilter的作用 This filter looks at the incoming URL maps them to handlers defined in solrcon ...

  10. BZOJ 1925 地精部落(DP)

    一道很经典的DP题. 题意:求n排列中波动排列的种数. 不妨考虑DP,令dp1[i][j],表示1-j的排列中,第一项为i之后递增的波动排列种数.dp2[i][j]表示1-j的排列中,第一项为i之后递 ...