BZOJ 1066 蜥蜴

传送门

题解:这题就是HDU2732的中文题面。。。蜥蜴跳的距离是曼哈顿距离。建一个源点对每一个L所在的地方建一个容量为1的边,对柱子如果能跳出去就与汇点建一个容量为柱子容量的边,柱子的出点与入点建一个容量INF的边,柱子与柱子之间只要满足条件就将一个柱子的出点,与另一个柱子的入点建一条为柱子容量的边

 
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <cstring>
#include <iomanip>
#include <set>
#include<ctime>
//CLOCKS_PER_SEC
#define se second
#define fi first
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Pii pair<int,int>
#define Pli pair<ll,int>
#define ull unsigned long long
#define pb push_back
#define fio ios::sync_with_stdio(false);cin.tie(0)
const double Pi=3.14159265;
const int N=1e5+50;
const ull base=163;
const int INF=0x3f3f3f3f;
using namespace std;
int head[N],nx[N],to[N],cap[N],cur[N];
int s,t;
int tot=0;
void add(int u,int v,int c){
    nx[tot]=head[u];
    to[tot]=v;
    cap[tot]=c;
    head[u]=tot++;
     
    nx[tot]=head[v];
    to[tot]=u;
    cap[tot]=0;
    head[v]=tot++;
}
int d[N];
int bfs(){
    memset(d,-1,sizeof(d));
    queue<int>q;
    q.push(s);
    d[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];~i;i=nx[i]){
            int v=to[i];
            if(d[v]==-1&&cap[i]>0){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[t]!=-1;
}
int dfs(int s,int a){
    if(s==t||a==0)return a;
    int flow=0,f;
    for(int &i=cur[s];~i;i=nx[i]){
        int v=to[i];
        if(d[v]==d[s]+1&&cap[i]>0&&(f=dfs(v,min(a,cap[i])))){
            flow+=f;
            cap[i]-=f;
            cap[i^1]+=f;
            a-=f;
            if(a==0)break;
        }
    }
    return flow;
}
int dinic(){
    int ans=0;
    while (bfs()) {
        for(int i=0;i<=t;i++)cur[i]=head[i];
        while(int di=dfs(s,INF))ans+=di;
    }
    return ans;
}
char mat[100][100];
char str[100][100];
int cal(int x,int y,int a,int b){
    return abs(x-a)+abs(y-b);
}
vector<Pii>vec;
int main(){// s--0  出n*m+m*i+j+30  入m*i+j
    s=0,t=2000;
    int n,m,f;
    scanf("%d%d%d",&n,&m,&f);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++){
        scanf("%s",mat[i]+1);
        for(int j=1;j<=m;j++){
            if(mat[i][j]!='0'){
                vec.pb({i,j});
                add(m*i+j,n*m+m*i+j+30,mat[i][j]-'0');
                if(i<=f||j<=f||(n-i)<f||(m-j)<f){
                    add(n*m+30+m*i+j,t,mat[i][j]-'0');//可以跳出去
                }
            }
        }
    }
    for(int i=0;i<vec.size();i++){
        Pii u=vec[i];
        for(int j=i+1;j<vec.size();j++){
            Pii v=vec[j];
            if(cal(u.fi,u.se,v.fi,v.se)<=f){
                //cout<<"fds";
                add(n*m+m*u.fi+u.se+30,m*v.fi+v.se,INF);
                add(n*m+m*v.fi+v.se+30,m*u.fi+u.se,INF);
            }
        }
    }
    int ss=0;
    for(int i=1;i<=n;i++){
        scanf("%s",str[i]+1);
        for(int j=1;j<=m;j++){
            if(str[i][j]=='L'){
                ss++;
                add(0,m*i+j,1);
            }
        }
    }
    int d=dinic();
     
    int ans=ss-d;
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2018-05-27 22:27  采蘑菇的小西佬  阅读(217)  评论(0编辑  收藏  举报