蜥蜴(bzoj 1066)

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

/*
  挺简单的一道题,搞了将近两个小时,dinic的板子打错了一个地方,找了很长时间。
  把每个有柱子的点进行拆点,连一条容量为a[i][j]的边,以表示每个点能用的次数,
  源点向每个出发点连一条容量为1的边,每个可到达边界的点向汇点连一条容量为inf的边,
  两个互相可到达的点之间连一条容量为inf的点。
*/
#include<cstdio>
#include<cmath>
#include<iostream>
#define N 1010
#define M 100010
#define inf 1000000000
using namespace std;
int a[25][25],head[N],dis[N],q[N],r,c,d,n,m,S,T,cnt=1,ans;
struct node{
    int v,pre,f;
};node e[M];
void add(int u,int v,int f){
    e[++cnt].v=v;e[cnt].f=f;e[cnt].pre=head[u];head[u]=cnt;
    e[++cnt].v=u;e[cnt].f=0;e[cnt].pre=head[v];head[v]=cnt;
}
double dist(int x1,int y1,int x2,int y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool bfs(){
    for(int i=1;i<=T;i++)dis[i]=inf;
    int h=0,t=1;q[1]=S;dis[S]=0;
    while(h<t){
        int x=q[++h];
        for(int i=head[x];i;i=e[i].pre){
            int v=e[i].v;
            if(e[i].f&&dis[v]>dis[x]+1){
                dis[v]=dis[x]+1;
                if(v==T)return true;
                q[++t]=v;
            }
        }
    }
    return dis[T]!=inf;
}
int dinic(int now,int f){
    if(now==T)return f;
    int rest=f;
    for(int i=head[now];i;i=e[i].pre){
        int v=e[i].v;
        if(dis[v]==dis[now]+1&&e[i].f){
            int t=dinic(v,min(e[i].f,rest));
            if(!t)dis[v]=0;
            e[i].f-=t;
            e[i^1].f+=t;//写成减号了!!!
            rest-=t;
        }
    }
    return f-rest;
}
int main(){
    scanf("%d%d%d",&r,&c,&d);
    S=0;T=2*r*c+1;
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++){
            char ch;cin>>ch;
            a[i][j]=ch-‘0‘;
            if(a[i][j]&&(i-d<=0||i+d>r||j-d<=0||j+d>c))add((i-1)*c+j+T/2,T,inf);
        }
    for(int x1=1;x1<=r;x1++)
        for(int y1=1;y1<=c;y1++){
            if(!a[x1][y1])continue;
            for(int x2=1;x2<=r;x2++)
                for(int y2=1;y2<=c;y2++){
                    if(x1==x2&&y1==y2)continue;
                    if(dist(x1,y1,x2,y2)<=d)add((x1-1)*c+y1+T/2,(x2-1)*c+y2,inf);
                }
        }
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++){
            char ch;cin>>ch;
            if(ch==‘L‘)add(S,(i-1)*c+j,1),ans++;
        }
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
            if(a[i][j])add((i-1)*c+j,(i-1)*c+j+T/2,a[i][j]);
    while(bfs())ans-=dinic(S,inf);
    printf("%d",ans);
    return 0;
}
时间: 2024-10-26 03:04:17

蜥蜴(bzoj 1066)的相关文章

AC日记——[SCOI2007]蜥蜴 bzoj 1066

1066 思路: 网络流最大流: 拆点,每个点拆成两个,流量为这个点的高度: 注意,文中说的距离是曼哈顿距离(劳资以为开根号wa了不知道多少次): 每两个距离不大于d的点连边,流量inf: 如果距离能够延伸到边界外,就将这个点连向t: 最后输出,蜥蜴个数减去最大流: 来,上代码: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <alg

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

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

BZOJ 1066 [SCOI2007]蜥蜴(最大流)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1066 [题目大意] 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴, 你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1, 蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上. 石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1 (如果仍然落在地图内部,则到达的石柱高度不变), 如果该石柱原来高度为1,则蜥蜴离开后消失.以后其

【BZOJ 1066】[SCOI2007]蜥蜴

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

bzoj 1066 : [SCOI2007]蜥蜴 网络流

题目链接 给一个n*m的图, 里面每一个点代表一个石柱, 石柱有一个高度. 初始时有些石柱上面有蜥蜴, 蜥蜴可以跳到距离他曼哈顿距离小于等于d的任意一个石柱上,跳完后, 他原来所在的石柱高度会减一, 如果高度变为0, 那么石柱消失, 无法在跳到这个位置上, 跳到的那个石柱高度不会发生改变, 同一时刻一个石柱无法站两个蜥蜴.问有多少蜥蜴无法跳出边界. 很裸的网络流, 如果一个石柱距离边界距离小于d, 那么向汇点连一条权值为inf的边, 如果一个石柱初始有蜥蜴, 那么源点向这个点连一条1的边, 每个

[BZOJ 1066][SCOI2007]蜥蜴(网络流)

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

bzoj 1066 蜥蜴

网络流. 建图:首先将每根柱子拆成两个点. 每根柱子的入点向出点连一条容量为柱子高度的边. 每根柱子的出点向可以到达的柱子的入点连一条容量为正无穷的边. 源点向每根初始有蜥蜴的柱子的入点连一条容量为一的边. 每根可以跳出地图的柱子的出点向汇点连一条容量为正无穷的边. 跑一遍最大流就是最多能逃出的蜥蜴数. 1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream&

BZOJ 1066 SCOI 2007 蜥蜴 最大流

题目大意:给出一张图,每一个点有一个寿命,当有这个寿命值个蜥蜴经过后这个点就会消失,一个蜥蜴可以跳到距离不超过d的点上,问最少有多少只蜥蜴无法跳出这张图. 思路:我们将每个点拆点,然后限制流量为这个点的寿命,之后源点向每个蜥蜴连边,互相能够到达的点之间连边,能够跳出这个图的点和汇点连边,跑最大流就是这个图中最多能够跑出去的蜥蜴数量,最后在用总数减去就是最少不能逃出去的数量. CODE: #include <cmath> #include <queue> #include <c

bzoj 1066: [SCOI2007]蜥蜴

1 #include<cstdio> 2 #include<iostream> 3 #define T 1001 4 #define M 10005 5 #define inf 0x7fffffff 6 #include<cstring> 7 using namespace std; 8 int cnt=1,r,c,d,head[M],next[10*M],u[10*M],v[10*M],sum,f[25][25],d1[M],q[M],ans; 9 char ch[5