bzoj1066 蜥蜴

Description

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

Input

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

Output

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

Sample Input

5 8 2

00000000

02000000

00321100

02000000

00000000

........

........

..LLLL..

........

........

Sample Output

1

HINT

100%的数据满足:1<=r, c<=20, 1<=d<=4

虽然它需要每个蜥蜴不能同时在同一石柱上,但是实际上我们可以让蜥蜴按一定顺序一个一个走,不同时走。那这些排列顺序里一定有一种方案是最优的。

为什么呢?因为最优解不可能出现蜥蜴A跳出去的路径中经过蜥蜴B的初始位置(标记为A->B),并且蜥蜴B跳出去的路径中经过蜥蜴A的初始位置(标记为B->A)。

也就是说要么蜥蜴A跳出去的路径中经过蜥蜴B的初始位置,那么蜥蜴B应该排在蜥蜴A前面走;要么蜥蜴B跳出去的路径中要经过蜥蜴A的初始位置,那么蜥蜴A应该排在蜥蜴B前走。

同样更不会出现A->B且B->C且C->A的情况、A->B且B->C且C->D且D->A的情况,等等。也就是说这个一定是有拓扑序的,不会有环。

那么我们在跑网络流的时候可以不用管它的顺序,直接跑最大流,只要是可行流就一定是可行解,因为一定会有一个蜥蜴的排列顺序满足这个可行流。每个石柱拆成两个点,这两个点间连一条最大流量为石柱高度的点,从S向每个蜥蜴所在石柱连一条最大流量为1的边。T与每个能跳出地图的石柱连一条最大流量为INF的边。石柱与石柱间若距离<=d也相互连最大流量为INF的边。

所以就拆点Dinic。

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=400*2+10,maxm=maxn*maxn,INF=0x3f3f3f3f;
int n,r,c,d,tot_col,tot_m,sz,S,T;
int bh[maxn][maxn];
char kk;

struct Col{
    int x,y,h;
}col[maxn];

int aa,ff;char cc;
int read() {
    aa=0;ff=1;cc=getchar();
    while(cc<‘0‘||cc>‘9‘) {
        if(cc==‘-‘) ff=-1;
        cc=getchar();
    }
    while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar();
    return aa*ff;
}

struct Node{
    int x,y,flow,cap;
    Node(){}
    Node(int x,int y,int cap):x(x),y(y),cap(cap){flow=0;}
}node[2*maxm];

int cur[maxn],fir[maxn],nxt[2*maxm],e=1;
void add(int x,int y,int z) {
    node[++e]=Node(x,y,z); nxt[e]=fir[x];fir[x]=e;
    node[++e]=Node(y,x,0); nxt[e]=fir[y];fir[y]=e;
}

int dis[maxn],zz[maxn];
bool BFS() {
    int s=1,t=0,x,y,z;
    memset(dis,-1,sizeof(dis));
    dis[S]=0;zz[++t]=S;
    while(s<=t) {
        x=zz[s];
        for(y=fir[x];y;y=nxt[y]) {
            z=node[y].y;
            if(dis[z]!=-1||node[y].flow>=node[y].cap) continue;
            dis[z]=dis[x]+1;
            zz[++t]=z;
        }
        s++;
    }
    return dis[T]!=-1;
}

int DFS(int pos,int maxf) {
    if(pos==T||!maxf) return maxf;
    int now,z,rs=0;
    for(int &y=cur[pos];y;y=nxt[y]) {
        z=node[y].y;
        if(dis[z]!=dis[pos]+1||node[y].flow>=node[y].cap) continue;
        now=DFS(z,min(maxf,node[y].cap-node[y].flow));
        node[y].flow+=now; node[y^1].flow-=now;
        maxf-=now; rs+=now;
    }
    if(!rs) dis[pos]=-1;
    return rs;
}

int Dinic() {
    int rs=0;
    while(BFS()) {
        memcpy(cur,fir,sizeof(fir));
        rs+=DFS(S,INF);
    }
    return rs;
}

bool ok(int x,int y) {
    return sqrt((double)(col[x].x-col[y].x)*(col[x].x-col[y].x)+(double)(col[x].y-col[y].y)*(col[x].y-col[y].y))<=(double)d;
}

int main() {
    r=read();c=read();d=read(); int x;
    for(int i=1;i<=r;++i) {
        kk=getchar();
        while(kk<‘0‘||kk>‘9‘) kk=getchar();
        x=kk-‘0‘;
        for(int j=1;j<=c;++j) {
            if(x) {
                col[++tot_col].x=i;
                col[tot_col].y=j;
                col[tot_col].h=x;
                bh[i][j]=tot_col;
            }
            kk=getchar();x=kk-‘0‘;
        }
    }
    S=2*tot_col+1;T=S+1;
    for(int i=1;i<=tot_col;++i) {
        add(i,i+tot_col,col[i].h);
        if(min(col[i].x,r-col[i].x+1)<=d||min(col[i].y,c-col[i].y+1)<=d) add(i+tot_col,T,INF);
        for(int j=1;j<=tot_col;++j){
            if(i==j) continue;
            else if(ok(i,j)) add(i+tot_col,j,INF);
        }
    }
    for(int i=1;i<=r;++i) {
        kk=getchar();
        while(kk!=‘.‘&&kk!=‘L‘) kk=getchar();
        for(int j=1;j<=c;++j) {
            if(kk==‘L‘)
                add(S,bh[i][j],1),n++;
            kk=getchar();
        }
    }
    printf("%d",n-Dinic());
    return 0;
}

  

时间: 2024-10-01 06:40:37

bzoj1066 蜥蜴的相关文章

【bzoj1066】: [SCOI2007]蜥蜴 图论-最大流

[bzoj1066]: [SCOI2007]蜥蜴 把石柱拆点,流量为高度 然后S与蜥蜴连流量1的边 互相能跳到的石柱连inf的边 石柱能到边界外的和T连inf的边 然后跑dinic就好了 1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <al

bzoj1066[SCOI2007]蜥蜴

bzoj1066[SCOI2007]蜥蜴 题意: r行c列网格图上有一些高低不平的柱子,一些柱子上有蜥蜴,一只蜥蜴一次能跳距离为d,每次蜥蜴跳跃时出发柱子高度减一,当柱子高度为0时消失,问最少多少蜥蜴不能跳出网格图.r,c≤20,d≤4 题解: 裸最大流,每个柱子拆成X,Y两点,两点之间连柱子的高度,所有Yi向可达柱子的Xi连边,s向所有蜥蜴初始位置连边,所有可以跳出图的柱子向t连边. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #

【bzoj1066】[SCOI2007]蜥蜴 网络最大流

[bzoj1066][SCOI2007]蜥蜴 Description 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上.石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失.以后其他蜥蜴不能落脚.任何时刻不能有两只蜥蜴在同一个石柱上. Input 输入第

[BZOJ1066][luogu_P2472][SCOI2007]蜥蜴

[BZOJ1066][luogu_P2472][SCOI2007]蜥蜴 试题描述 在一个 \(r\) 行 \(c\) 列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为 \(1\),蜥蜴的跳跃距离是 \(d\),即蜥蜴可以跳到平面距离不超过 \(d\) 的任何一个石柱上.石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减 \(1\)(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为 \(1\),则蜥蜴离开

bzoj1066【SCOI2007】蜥蜴

1066: [SCOI2007]蜥蜴 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2512  Solved: 1238 [Submit][Status][Discuss] Description 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上.石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱

[BZOJ1066] [SCOI2007] 蜥蜴 (网络流)

Description 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上.石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失.以后其他蜥蜴不能落脚.任何时刻不能有两只蜥蜴在同一个石柱上. Input 输入第一行为三个整数r,c,d,即地图的规模与最大跳

51nod 1489 蜥蜴和地下室

题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 哈利喜欢玩角色扮演的电脑游戏<蜥蜴和地下室>.此时,他正在扮演一个魔术师.在最后一关,他必须和一排的弓箭手战斗.他唯一能消灭他们的办法是一个火球咒语.如果哈利用他的火球咒语攻击第i个弓箭手(他们从左到右标记),这个弓箭手会失去a点生命值.同时,这个咒语使与第i个弓箭手左右相邻的弓箭手(如果存在)分别失去b(1 ≤ b < a ≤ 10)点生命值. 因为两个端点的弓箭手(即

[BZOJ 1066] [SCOI2007] 蜥蜴 【最大流】

题目链接:BZOJ - 1066 题目分析 题目限制了高度为 x 的石柱最多可以有 x 只蜥蜴从上面跳起,那么就可以用网络流中的边的容量来限制.我们把每个石柱看作一个点,每个点拆成 i1, i2,从 i1 到 i2 连一条边,容量为这个石柱 i 的高度,即跳跃次数限制.来到这个石柱就是向 i1 连边,从这个石柱跳起就是从 i2 向外连边,这样只要从石柱 i 跳起就一定会消耗 i1 到 i2 的边的容量.如果 i 有蜥蜴,就从 S 到 i1 连一条容量为 1 的边,如果从石柱 i 能跳出边界,就从

【网络流】【BZOJ1006】【SCOI2007】蜥蜴

学弟@lher在周末训练赛中出的题目的原题(这个人拿省选题来当作提高组模拟,太丧了...) 链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1066 题意简析:看题目:) 解题思路:题目显然是最大流. 首先拆点将点权变为边权,然后按照题意对于所有有跳板的点向可以跳到的点连一条权值为inf的边,对于能够跳出地图边界的点,将它与汇点连一条权值为inf的边.对于有蜥蜴的点,从源点向这个点连一条权值为1的边,然后跑一次最大流,答案就是蜥蜴数-最大流.