题目的大意是有个n*m的grid,每个位置上都有柱子,柱子有一定的高度,有一群lizard想逃出这个grid,lizard一次最远可以跳d。
grid的四边是安全的,每个柱子一次上面最多有一只lizard,lizard可以跳到一个可以跳到且上面没有lizard的柱子上面同时它原来所在的柱子的高度会-1,为0时就不能再往上面跳了。
思路就是把柱子拆点,容量为其高度。lizard可以一次性从其跳到安全区的话就和汇点t连接,容量为inf;上面有人的话就和源点s连接,容量为1。
两个柱子的距离在d之内也连接起来,容量为inf。
/***************************************** Author :Crazy_AC(JamesQi) Time :2016 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; typedef pair<ii,int> iii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 1100; const int maxm = 1400000; char mp1[maxn][maxn],mp2[maxn][maxn]; int n, d, m; int s, t; int head[maxn], cap[maxm], flow[maxm], nxt[maxm],pnt[maxm]; int ecnt; inline void Addedge(int u,int v,int c) { pnt[ecnt] = v, flow[ecnt] = 0, cap[ecnt] = c; nxt[ecnt] = head[u], head[u] = ecnt++; pnt[ecnt] = u, flow[ecnt] = 0, cap[ecnt] = 0; nxt[ecnt] = head[v], head[v] = ecnt++; } inline void Input() { scanf("%d%d",&n,&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); m = strlen(mp1[1] + 1); s = n*m*2+1,t = s + 1; memset(head, -1,sizeof head); ecnt = 0; } inline int Getmap() { //拆点 for (int i = 1;i <= n;++i) { for (int j = 1;j <= m;++j) { if (mp1[i][j] - '0') {//柱子上面可以跳 Addedge((i-1)*m+j, n*m+(i-1)*m+j, mp1[i][j] - '0'); } } } int cnt = 0; for (int i = 1;i <= n;++i) { for (int j = 1;j <= m;++j) { if (mp2[i][j] == 'L') {//这个位置上有人 Addedge(s, (i-1)*m+j, 1);cnt++; } } } for (int i = 1;i <= n;++i) { for (int j = 1;j <= m;++j) { if (i <= d || j <= d || j > m - d || i > n - d) Addedge((i-1)*m+j + n*m, t, INF); } } for (int i = 1;i <= n;++i) { for (int j = 1;j <= m;++j) { for (int l = 1;l <= n;++l) { for (int r = 1;r <= m;++r) { if (!(i==l && j==r) && abs(i-l) + abs(j-r) <= d) Addedge((i-1)*m+j+n*m,(l-1)*m+r, INF); } } } } return cnt; } int dis[maxn]; bool vis[maxn]; bool spfa() { queue<int> que; memset(dis, -1,sizeof dis); memset(vis, false,sizeof vis); que.push(s); dis[s] = 0; vis[s] = true; while(!que.empty()) { int u = que.front(); que.pop(); for (int i = head[u];i != -1;i = nxt[i]) { int v = pnt[i]; if (cap[i] - flow[i] > 0 && dis[v] == -1) { dis[v] = dis[u] + 1; que.push(v); } } } return dis[t] != -1; } int dfs(int u,int a) { if (u == t || a == 0) return a; int ret = 0,f; for (int i = head[u];i != -1;i = nxt[i]) { int v = pnt[i]; if (dis[v] > dis[u] && (f = dfs(v, min(a, cap[i] - flow[i]))) > 0) { ret += f; a -= f; flow[i] += f; flow[i^1] -= f; if (a==0)break; } } return ret; } inline int dinic() { int ret = 0; while(spfa()) { ret += dfs(s, INF); } return ret; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int tt; scanf("%d",&tt); int icase = 0; while(tt--) { Input(); int cnt = Getmap(); int ans = dinic(); // printf("cnt = %d, ans = %d\n",cnt,ans); printf("Case #%d: ", ++icase); if (cnt == ans) printf("no lizard was left behind.\n"); if (ans + 1 == cnt) printf("1 lizard was left behind.\n"); if (ans + 1 < cnt) printf("%d lizards were left behind.\n", cnt - ans); } return 0; }