BZOJ1066 SCOI2007 蜥蜴 【网络流-最大流】

114 篇文章 0 订阅
24 篇文章 1 订阅

BZOJ1066 SCOI2007 蜥蜴


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


一道比较裸的(套路)最大流板子
把一个石柱点分成进和出两个部分,中间连一条容量为高度的边
然后就可以做完了


//yangkai
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 10010 
struct Edge{int u,v,cap,flow;};
struct Dinic{
    int s,t;
    int vis[N],d[N];
    vector<Edge> E;
    vector<int> G[N];
    void add(int u,int v,int cap){
        E.push_back((Edge){u,v,cap,0});
        E.push_back((Edge){v,u,0,0});
        int cnt=E.size();
        G[u].push_back(cnt-2);
        G[v].push_back(cnt-1);      
    }
    bool BFS(){
        memset(vis,0,sizeof(vis));
        memset(d,0,sizeof(d));
        queue<int> Q;
        Q.push(s);
        vis[s]=1;
        while(!Q.empty()){
            int u=Q.front();Q.pop();
            for(int i=0;i<G[u].size();i++){
                Edge &e=E[G[u][i]];
                if(!vis[e.v]&&e.cap>e.flow){
                    vis[e.v]=1;
                    d[e.v]=d[u]+1;
                    Q.push(e.v);
                }
            }
        }
        return vis[t];
    }
    int DFS(int u,int a){
        if(u==t||!a)return a;
        int flow=0;
        for(int i=0;i<G[u].size();i++){
            Edge &e=E[G[u][i]];
            if(d[e.v]!=d[u]+1)continue;
            int f=DFS(e.v,min(a,e.cap-e.flow));
            e.flow+=f;
            E[G[u][i]^1].flow-=f;
            flow+=f;
            a-=f;
            if(!a)break;
        }
        return flow;
    }
    int Maxflow(){
        int flow=0;
        while(BFS())
            flow+=DFS(s,INF);
        return flow;
    }
}dinic;
int w,h,d,sum=0;
int g[30][30],p[30][30];
char op[30];
bool judge_in(int x1,int x2,int y1,int y2){
    return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<=d*d;
}
int getid(int x,int y){
    return (x-1)*h+y;
}
void build(){
    dinic.s=0;dinic.t=w*h*2+1;
    for(int i=1;i<=w;i++)
        for(int j=1;j<=h;j++)
            if(p[i][j])dinic.add(dinic.s,getid(i,j)*2-1,1);
    for(int i=1;i<=w;i++)
        for(int j=1;j<=h;j++)
            if(i<=d||i>=(w-d+1)||j<=d||j>=(h-d+1))
                dinic.add(getid(i,j)*2,dinic.t,INF);
    for(int i=1;i<=w;i++)
        for(int j=1;j<=h;j++)
            for(int ii=1;ii<=w;ii++)
                for(int jj=1;jj<=h;jj++)
                    if(judge_in(i,ii,j,jj))
                        dinic.add(getid(i,j)*2,getid(ii,jj)*2-1,INF);
    for(int i=1;i<=w;i++)
        for(int j=1;j<=h;j++)
            if(g[i][j])dinic.add(getid(i,j)*2-1,getid(i,j)*2,g[i][j]);
}
int main(){
    cin>>w>>h>>d;
    for(int i=1;i<=w;i++){
        scanf("%s",op+1);
        for(int j=1;j<=h;j++)g[i][j]=op[j]-'0';
    }
    for(int i=1;i<=w;i++){
        scanf("%s",op+1);
        for(int j=1;j<=h;j++){
            p[i][j]=(op[j]=='L')?1:0;
            sum+=p[i][j];
        }
    }
    build();
    cout<<sum-dinic.Maxflow();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值