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; }