先预处理出来每个ghost到每个human后杀掉他后返回窝的最少时间。
然后人份时间上限建图,二分匹配判断匹配数目是否等于human的数目。。。
/***************************************** Author :Crazy_AC(JamesQi) Time :2015 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 N = 30; int dx[] = {-1,0,1,0}; int dy[] = {0,-1,0,1}; vector<ii> G[N*N]; char g[N][N]; int n; int A[N][N], B[N][N]; int uN, vN; void input() { scanf("%d",&n); uN = vN = 0; memset(A, 0,sizeof A); memset(B, 0,sizeof B); for (int i = 1;i <= n;++i) { scanf("%s", g[i] + 1); for (int j = 1;j <= n;++j) { if (g[i][j] == 'G') { A[i][j] = ++uN; } if (g[i][j] == 'H') { B[i][j] = ++vN; } } } } bool vis[N][N]; int dis[N][N]; bool check(int x,int y) { if (vis[x][y]) return false; if (x < 1 || x > n || y < 1 || y > n || g[x][y] == '#') return false; return true; } void bfs(int x,int y) { memset(vis, false,sizeof vis); memset(dis, -1,sizeof dis); dis[x][y] = 0; vis[x][y] = true; queue<ii> que; que.push(ii(x, y)); while(!que.empty()) { ii tmp = que.front(); que.pop(); for (int i = 0;i < 4;++i) { int nx = tmp.first + dx[i]; int ny = tmp.second + dy[i]; if (check(nx,ny)) { dis[nx][ny] = dis[tmp.first][tmp.second] + 1; que.push(ii(nx,ny)); vis[nx][ny] = true; if (g[nx][ny] == 'H') { G[A[x][y]].push_back(ii(B[nx][ny], dis[nx][ny] * 2 + 2)); } } } } } void Initation() { for (int i = 1;i <= uN;++i) G[i].clear(); for (int i = 1;i <= n;++i) { for (int j = 1;j <= n;++j) { if (g[i][j] == 'G') bfs(i, j); } } } vector<int> mp[N*N]; void getmap(int x) { for (int i = 1;i <= uN;++i) { mp[i].clear(); for (int j = 0;j < G[i].size();++j) { if (G[i][j].second <= x) mp[i].push_back(G[i][j].first); } } } int linker[N*N]; bool mark[N*N]; bool search(int u) { for (int i = 0;i < mp[u].size();++i) { int v = mp[u][i]; if (mark[v]) continue; mark[v] = true; if (linker[v] == -1 || search(linker[v])) { linker[v] = u; return true; } } return false; } int hungary() { int ans = 0; memset(linker, -1,sizeof linker); for (int i = 1;i <= uN;++i) { memset(mark, false,sizeof mark); if (search(i)) ans++; } return ans; } int binary() { int ans = -1; int low = 1, high = 100000; while(low <= high) { int mid = (low + high) / 2; getmap(mid); int tmp = hungary(); if (tmp == vN) { ans = mid; high = mid - 1; }else low = mid + 1; } return ans; } int main() { // freopen("in.txt","r",stdin); // freopen("out1.txt","w",stdout); int t, icase = 0; scanf("%d",&t); while(t--) { input(); Initation(); int ans = binary(); printf("Case %d: ", ++icase); if (ans == -1) puts("Vuter Dol Kupokat"); else printf("%d\n", ans); } return 0; }