bzoj 1066: [SCOI2007]蜥蜴

题目链接

bzoj 1066: [SCOI2007]蜥蜴

题解

对于每块石头拆点限流为高度
限制跳跃次数
对于能跳出去的石头的连接汇点容量为INF
源点连接青蛙容量为1
对于互相能到达的点建立容量为INF的边
求出最大流为做多逃出数
答案为青蛙数-最大流

代码

#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#define INF 0x7fffffff
using std::queue;
const int maxn=1010;
struct node {
    int v,next,flow;
}edge[maxn*50];int num=1;
int r,c,d,S,T,cur[maxn],head[maxn],lev[maxn];
char s[31];
int mp[31][31];
void add_edge(int u,int v,int flow) {
    edge[++num].v=v;edge[num].flow=flow;edge[num].next=head[u];head[u]=num;
    edge[++num].v=u;edge[num].flow=0;edge[num].next=head[v];head[v]=num;
}
double calc_dis(int x1,int y1,int x2,int y2) {return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
int calc_pos(int x,int y,int add) {return (x-1)*c+y+r*c*add;}
bool judge(int x,int y) {return x<=d||r-x<d||y<=d||c-y<d;}
bool spfa() {
    memset(lev,-1,sizeof lev);
    memcpy(cur,head,sizeof head);
    queue<int>que;
    que.push(S);lev[S]=0;
    while(!que.empty()) {
        int u=que.front();que.pop();
        for(int i=head[u];i;i=edge[i].next) {
            int v=edge[i].v;
            if(edge[i].flow>0&&lev[v]<0) {
                lev[v]=lev[u]+1;que.push(v);
            }
        }
    }
    if(lev[T]!=-1)return true;
    else return false;
}   
int dfs(int now,int flow) {
    if(now==T)return flow;
    int rest=0,delta;
    for(int &i=cur[now];i;i=edge[i].next) {
        int v=edge[i].v;
        if(lev[v]==lev[now]+1&&edge[i].flow>0) {
            delta=dfs(v,std::min(flow-rest,edge[i].flow));
            if(delta) {
                edge[i].flow-=delta;
                edge[i^1].flow+=delta;
                rest+=delta;if(rest==flow)break;
            }
        }
    }
    if(rest==flow)lev[now]=-1;
    return rest;
}
int dinic() {
    int ret=0;
    while(spfa())
        ret+=dfs(S,INF);
    return ret;
}
int main(){
    int cnt=0;
    scanf("%d%d%d",&r,&c,&d); T=2*r*c+1;
    for(int i=1;i<=r;i++){
        scanf("%s",s+1);
        for(int j=1;j<=c;j++) mp[i][j]=s[j]-'0';
    }
    for(int i=1;i<=r;i++) {
        scanf("%s",s+1);
        for(int j=1;j<=c;j++) {
            if(s[j]=='L') cnt++,add_edge(S,calc_pos(i,j,0),1);
        }
    }
    for(int i=1;i<=r;i++) 
        for(int j=1;j<=c;j++) 
            if(mp[i][j]) add_edge(calc_pos(i,j,0),calc_pos(i,j,1),mp[i][j]);
    for(int x1=1;x1<=r;x1++) 
        for(int y1=1;y1<=c;y1++) {
            if(!mp[x1][y1]) continue;
            for(int x2=1;x2<=r;x2++) 
                for(int y2=1;y2<=c;y2++) {
                    if(x1==x2&&y1==y2) continue;
                    if(mp[x2][y2]&&calc_dis(x1,y1,x2,y2)<=d) {
                        add_edge(calc_pos(x1,y1,1),calc_pos(x2,y2,0),INF);
                        add_edge(calc_pos(x2,y2,1),calc_pos(x1,y1,0),INF);
                    }
                }
    	}
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
            if(judge(i,j)) add_edge(calc_pos(i,j,1),T,INF);
    printf("%d",cnt-dinic());
    return 0;
}
posted @ 2018-02-10 21:33  zzzzx  阅读(170)  评论(0编辑  收藏  举报