【bzoj1066】【SCOI2007】蜥蜴

题目描述

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

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


输入

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


输出

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


样例输入

5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........


样例输出

1

 



题解

最大流。

考虑到柱子之间可以相互跳,于是要拆点。把一个点拆成入点和出点,入点出点之间连流量为柱子高度的边。

建立超级源点,向每个蜥蜴连流量为 1 的边。

建立超级汇点,向可以走出格子的点连流量为 inf 的边。

可以相互到达的柱子之间连 inf 的边。

跑最大流。

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int maxn=20+10;
const int inf=2e9;

int r,c,dd,s=0,t=801,ru[1000],chu[1000],d[1000],maxflow,x,tot;
int fir[1000],nex[100000],to[100000],wi[100000],ecnt;
char high[maxn][maxn],Map[maxn][maxn];
bool p[800+50][800+50];

int getid(int x,int y){return (x-1)*c+y;}

void add(int u,int v,int w){
    nex[ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;wi[ecnt++]=w;
}

queue<int> q;

int bfs(){
    memset(d,0,sizeof(d));
    d[s]=1;
    q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int e=fir[u];~e;e=nex[e]){
            int v=to[e];
            if(wi[e]&&!d[v]){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[t];
}

int dfs(int u,int flow){
    if(u==t) return flow;
    if(d[u]>=d[t]) return 0;
    for(int e=fir[u];~e;e=nex[e]){
        int v=to[e];
        if(wi[e]&&d[v]==d[u]+1&&(x=dfs(v,min(flow,wi[e])))){
            wi[e]-=x;
            wi[e^1]+=x;
            return x;
        }
    }
    return 0;
}

template<typename T>inline void read(T &aa){
    ll ff=1;char cc=getchar();aa=0;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
    aa*=ff;
}

int main(){
    read(r),read(c),read(dd);
    for(int i=1;i<=r;i++) cin>>high[i]+1;
    for(int i=1;i<=r;i++) cin>>Map[i]+1;
    memset(fir,-1,sizeof(fir));
    for(int i=1;i<=r;i++)
    for(int j=1;j<=c;j++){
        int id=getid(i,j);
        ru[id]=id;chu[id]=id+400;
        if(Map[i][j]=='L') add(s,ru[id],1),add(ru[id],s,0),tot++;
        if(i<=dd||j<=dd||(r-i+1<=dd)||(c-j+1<=dd)) add(chu[id],t,inf),add(t,chu[id],0);
        if(high[i][j]-48==0) continue; 
        add(ru[id],chu[id],high[i][j]-48);
        add(chu[id],ru[id],0);
    }
    for(int i=1;i<=r;i++)
    for(int j=1;j<=c;j++){
        for(int ii=1;ii<=r;ii++)
        for(int jj=1;jj<=c;jj++){
            if(i==ii&&j==jj) continue;
            int id1=getid(i,j);
            int id2=getid(ii,jj);
            if(p[id1][id2]) continue;
            if((ii-i)*(ii-i)+(jj-j)*(jj-j)<=dd*dd){
                add(chu[id1],ru[id2],inf);
                add(ru[id2],chu[id1],0);
                add(chu[id2],ru[id1],inf);
                add(ru[id1],chu[id2],0);
            }
            p[id1][id2]=p[id2][id1]=true;
        }
    }
    while(bfs()) while(dfs(s,inf)) maxflow+=x;
    cout<<tot-maxflow;
    return 0;
}

 

posted @ 2018-11-07 19:23  rld  阅读(102)  评论(0编辑  收藏