网络流直接最大流就是了,只是要拆点小心一个点的流超出了原本的正常范围才是。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define HalF (l + r)>>1 #define lsn rt<<1 #define rsn rt<<1|1 #define Lson lsn, l, mid #define Rson rsn, mid+1, r #define QL Lson, ql, qr #define QR Rson, ql, qr #define myself rt, l, r using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 25, maxE = 3e4 + 7, st = 0; int N, D, M, all, head[807], cur[807], cnt, ed; char liz[maxN][maxN], jump[maxN][maxN]; struct Eddge { int nex, to, flow; Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), flow(c) {} }edge[maxE]; inline void addEddge(int u, int v, int w) { edge[cnt] = Eddge(head[u], v, w); head[u] = cnt++; } inline void _add(int u, int v, int w) { addEddge(u, v, w); addEddge(v, u, 0); } inline int _id(int x, int y) { return (x - 1) * M + y; } inline bool can_out(int x, int y) { return x <= D || y <= D || (N - x < D) || (M - y < D); } bool In_map(int x, int y) { return x >= 1 && y >= 1 && x <= N && y<= M; } int deep[807]; queue<int> Q; inline bool bfs() { for(int i=0; i<=ed; i++) deep[i] = 0; while(!Q.empty()) Q.pop(); Q.push(st); deep[st] = 1; while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i=head[u], v, f; ~i; i=edge[i].nex) { v = edge[i].to; f = edge[i].flow; if(f && !deep[v]) { deep[v] = deep[u] + 1; Q.push(v); } } } return deep[ed]; } inline int dfs(int u, int dist) { if(u == ed) return dist; for(int &i=cur[u], v, f; ~i; i=edge[i].nex) { v = edge[i].to; f = edge[i].flow; if(f && deep[v] == deep[u] + 1) { int di = dfs(v, min(dist, f)); if(di) { edge[i].flow -= di; edge[i^1].flow += di; return di; } } } return 0; } inline int Dinic() { int ans = 0, tmp; while(bfs()) { for(int i=0; i<=ed; i++) cur[i] = head[i]; while((tmp = dfs(st, INF))) ans += tmp; } return ans; } inline void init() { all =cnt = 0; memset(head, -1, sizeof(head)); } int main() { int T; scanf("%d", &T); for(int Cas=1; Cas<=T; Cas++) { scanf("%d%d", &N, &D); init(); for(int i=1; i<=N; i++) scanf("%s", jump[i] + 1); M = (int)strlen(jump[1] + 1); ed = 2 * N * M + 1; for(int i=1; i<=N; i++) { scanf("%s", liz[i] + 1); for(int j=1; j<=M; j++) { if(liz[i][j] == 'L') { all++; _add(st, _id(i, j), 1); } } } for(int i=1, u, v; i<=N; i++) { for(int j=1; j<=M; j++) { u = _id(i, j); if(jump[i][j] > '0') { _add(u, u + N * M, jump[i][j] - '0'); if(can_out(i, j)) { _add(u + N * M, ed, jump[i][j] - '0'); continue; } for(int x=0; x<=D; x++) { for(int y=D-x; y>=0; y--) { if(!x && !y) continue; if(In_map(i + x, j + y)) { v = _id(i + x, j + y); _add(u + N * M, v, jump[i][j] - '0'); } if(In_map(i - x, j + y)) { v = _id(i - x, j + y); _add(u + N * M, v, jump[i][j] - '0'); } if(In_map(i + x, j - y)) { v = _id(i + x, j - y); _add(u + N * M, v, jump[i][j] - '0'); } if(In_map(i - x, j - y)) { v = _id(i - x, j - y); _add(u + N * M, v, jump[i][j] - '0'); } } } } } } printf("Case #%d: ", Cas); int ans = all - Dinic(); if(ans == 0) printf("no lizard was left behind.\n"); else if(ans == 1) printf("1 lizard was left behind.\n"); else printf("%d lizards were left behind.\n", ans); } return 0; }