bzoj1066 [SCOI2007]蜥蜴

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1066

【题解】

网络流,考虑建模,拆点来满足限制跳多少次即可。

第2000个AC!

# include <queue>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, m, d, in[23][23], out[23][23], idx, S, T;
char mp1[23][23], mp2[23][23];

inline int dis2(int a, int b, int c, int d) {
    return (c-a)*(c-a)+(d-b)*(d-b);
}

int head[M], nxt[M], to[M], tot=1, flow[M];
inline void add(int u, int v, int fl) {
    ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; flow[tot] = fl;
}
inline void adde(int u, int v, int fl) {
    add(u, v, fl), add(v, u, 0);
}

namespace MF {
    queue<int> q; int c[M];
    inline bool bfs() {
        while(!q.empty()) q.pop();
        for (int i=1; i<=idx; ++i) c[i] = -1;
        c[S] = 1; q.push(S);
        while(!q.empty()) {
            int top = q.front(); q.pop();
            for (int i=head[top]; i; i=nxt[i]) {
                if(flow[i] == 0 || c[to[i]] != -1) continue;
                c[to[i]] = c[top] + 1;
                q.push(to[i]);
                if(to[i] == T) return 1;
            }
        }
        return 0;
    }
    inline int dfs(int x, int low) {
        if(x == T) return low;
        int r = low, fl;
        for (int i=head[x]; i; i=nxt[i]) {
            if(flow[i] == 0 || c[to[i]] != c[x] + 1) continue;
            fl = dfs(to[i], min(r, flow[i]));
            flow[i] -= fl;
            flow[i^1] += fl;
            r -= fl;
            if(!r) return low;
        }
        if(low==r) c[x]=-1;
        return low-r;
    }
    inline int main() {
        int ret = 0;
        while(bfs()) ret += dfs(S, 1e9);
        return ret;
    }
}
        


int main() {
    cin >> n >> m >> d;
    for (int i=1; i<=n; ++i) scanf("%s", mp1[i] + 1);
    for (int i=1; i<=n; ++i) scanf("%s", mp2[i] + 1);
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=m; ++j)
            in[i][j] = ++idx, out[i][j] = ++idx;
    S = ++idx, T = ++idx;
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=m; ++j) {
            bool hv = 0;
            for (int i1=max(0, i-d); i1<=min(n+1, i+d); ++i1)
                for (int j1=max(0, j-d); j1<=min(m+1, j+d); ++j1) {
                    if(dis2(i, j, i1, j1) <= d*d) {
                        if(i1==0||i1==n+1||j1==0||j1==m+1) {
                            if(!hv)    {
                                adde(out[i][j], T, 1e9);
                                hv = 1;
                            }
                        } else adde(out[i][j], in[i1][j1], 1e9);
                    }
                }
        }
    int all = 0;
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=m; ++j) 
            adde(in[i][j], out[i][j], mp1[i][j]-'0');
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=m; ++j)
            if(mp2[i][j] == 'L') {
                ++all;
                adde(S, in[i][j], 1);
            }
    
    cout << all - MF::main();
                
    return 0;
}
View Code

 

posted @ 2017-06-01 14:48  Galaxies  阅读(85)  评论(0编辑  收藏