zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    线程和信号
    线程取消状态和取消类型
    线程本地缓存
    线程安全函数的概念
    线程/同步对象的属性对象
    查看安全策略
    ss性能
    三次握手四次断开
    线程同步--屏障
    vs2008 编译时候 自动关闭 问题解决方法
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj1066.html
Copyright © 2011-2022 走看看