zoukankan      html  css  js  c++  java
  • 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;
    }
    
    

      

    弱者就是会被欺负呀
  • 相关阅读:
    2017-2018-1 20155306 《信息安全系统设计基础》第11周学习总结
    2017-2018-1 20155306 实验三 实时系统
    2017-2018-1 20155306 《信息安全系统设计基础》第9周学习总结
    2017-2018-1 20155306 mypwd的实现
    2017-2018-1 20155306 《信息安全系统设计基础》第8周课上测试+课下实践
    2017-2018-1 20155306 《信息安全系统设计基础》第8周学习总结
    2017-2018-1 20155306 《信息安全系统设计基础》第7周学习总结
    20155212——man指令的使用及mypwd的实现
    2017-2018-1 20155213 《信息安全系统设计基础》第七周学习总结
    2017-2018-1 20155213 20155303 实验二 固件程序设计
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7451347.html
Copyright © 2011-2022 走看看