bzoj1066 蜥蜴 (dinic)

最大流板子题。

对于每根柱子,建两个点ai,bi,建边(ai,bi,柱子高度)

对于距离不超过d的两根柱子i,j,建边(bi,aj,inf)

对于起始位置在i的每个蜥蜴,建边(S,ai,1)

对于能跳出地图的柱子i,建边(bi,E,inf)

然后跑dinic即可

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=23,inf=0x3f3f3f3f;

struct Edge{
    int a,b,v;
    int ne;
}eg[maxn*maxn*maxn*maxn*4];

int R,C,D,pcnt,rcnt,ecnt;
int map[maxn][maxn][2];
int rd[100][2];
int egh[maxn*maxn*2],P[maxn][maxn][2];
int deep[maxn*maxn*2];

inline void addedge(int a,int b,int v){
    eg[ecnt].a=a;eg[ecnt].b=b;eg[ecnt].v=v;eg[ecnt].ne=egh[a];egh[a]=ecnt++;
    eg[ecnt].a=b;eg[ecnt].b=a;eg[ecnt].v=0;eg[ecnt].ne=egh[b];egh[b]=ecnt++;
}

bool bfs(){
    queue<int> q;memset(deep,0,sizeof(deep));
    q.push(1);deep[1]=1;
    while(!q.empty()){
        int p=q.front();q.pop();
        for(int i=egh[p];i!=-1;i=eg[i].ne){
            if(eg[i].v&&!deep[eg[i].b]){
                q.push(eg[i].b);deep[eg[i].b]=deep[p]+1;
            }
        }
    }return deep[2];
}

int dinic(int x,int l){
    if(x==2)  return l;int tmp=l;
    for(int i=egh[x];i!=-1;i=eg[i].ne){
        if(deep[eg[i].b]!=deep[x]+1||!eg[i].v)  continue;
        int re=dinic(eg[i].b,min(eg[i].v,l));
        if(!re) deep[eg[i].b]=0;
        tmp-=re;eg[i].v-=re;eg[i^1].v+=re;
        if(!tmp)  break;
    }return l-tmp;
}

int main(){
    int i,j,k,ans=0;
    char s[maxn];
    //freopen("1066.in","r",stdin);
    scanf("%d%d%d",&R,&C,&D);
    for(i=1;i<=R;i++){
        scanf("%s",s+1);
        for(j=1;j<=C;j++)  map[i][j][0]=s[j]-'0';
    }
    for(i=1;i<=R;i++){
        scanf("%s",s+1);
        for(j=1;j<=C;j++)  map[i][j][1]=(s[j]=='L'?1:0);
    }
    for(i=-D;i<=D;i++){
        for(j=-D;j<=D;j++){
            if(i*i+j*j<=D*D){rd[rcnt][0]=i;rd[rcnt++][1]=j;}
        }
    }
    pcnt=2;memset(egh,-1,sizeof(egh));
    for(i=1;i<=R;i++)  for(j=1;j<=C;j++)  if(map[i][j][0]){
        P[i][j][0]=++pcnt;P[i][j][1]=++pcnt;addedge(P[i][j][0],P[i][j][1],map[i][j][0]);
        if(map[i][j][1])  {addedge(1,P[i][j][0],1);ans++;}
        }
    for(i=1;i<=R;i++){
        for(j=1;j<=C;j++){
            if(!map[i][j][0])  continue;
            bool b=0;
            for(k=0;k<rcnt;k++){
                int ii=i+rd[k][0],jj=j+rd[k][1];
                if(ii<=0||ii>R||jj<=0||jj>C)  b=1;
                else if(map[ii][jj])  addedge(P[i][j][1],P[ii][jj][0],inf);
            }if(b)  addedge(P[i][j][1],2,inf);
        }
    }
    while(bfs())  ans-=dinic(1,inf);
    printf("%d",ans);
}

 

posted @ 2018-07-23 14:11  Ressed  阅读(148)  评论(0编辑  收藏  举报