zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    Ruby on rails3新手谈(1):Ruby on rails环境搭建
    更灵活,更易维护的WebHandler之通用webHandler编码方案(2)
    .Net Remoting之windows服务部署
    Ruby on rails3新手谈(2):简单的例子helloworld
    分组取最新记录的SQL
    验证日期的Javascript
    使用Javascript创建遮罩层并模拟Alert、Confirm对话框
    取得当前鼠标的X,Y坐标,及相关属性的介绍
    B/S结构系统中使用Session遇到的问题
    IE与FireFox的兼容性问题
  • 原文地址:https://www.cnblogs.com/rlddd/p/9925078.html
Copyright © 2011-2022 走看看