題意:給一個矩陣,"."代表空地,“#”代表迷霧,“G”代表鬼,“H”代表人,每個鬼要嚇唬一個人,然後回到自己的位置,每走一格消耗一分鐘,嚇唬人消耗兩分鐘,每個鬼只能嚇唬一個人,求需要消耗的最小時間。
思路:用BFS求出所有鬼和人之間的邊,按照長短排序,每次放入一條邊然後求最大匹配,如果最大匹配與人的數量相同則成功,輸出當前邊的長度。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#define N 300
#define M 600
#define ll long long
#define INF 0x7fffffffffffffff
using namespace std;
struct Edge{
int h;
int g;
int length;
Edge(int _h,int _g,int _l){
this->h = _h,this->g = _g,this->length = _l;
}
};
struct Node{
int x;
int y;
int step;
Node(int _x,int _y,int _s){
x=_x,y=_y,step = _s;
}
};
vector<Edge>edges;//存邊
int maph[N][N];//人編號
char map[N][N];//地圖
bool mem[N][N];
vector <int>connect[M];
int match[M];
bool used[M];
bool canfound(int x){
for(int i=0;i<connect[x].size();i++){
int tmp = connect[x][i];
if(!used[tmp]){
used[tmp] = 1;
if(match[tmp] == -1 || canfound(match[tmp])){
match[tmp] = x;
return true;
}
}
}
return false;
}
int t,n;
int mx[4] = {-1,1,0,0};
int my[4] = {0,0,-1,1};
void bfs(int x,int y,int id){
queue<Node>Q;
Q.push(Node(x,y,0));
while (!Q.empty())
{
Node tmp = Q.front();Q.pop();
if(mem[tmp.x][tmp.y]){
continue;
}else{
mem[tmp.x][tmp.y] = 1;
}
if(map[tmp.x][tmp.y] == '#'){
continue;
}
if(maph[tmp.x][tmp.y] != 0){
edges.push_back(Edge(maph[tmp.x][tmp.y],id,tmp.step*2+2));
}
for(int i=0;i<4;i++){
if(tmp.x+mx[i] >= 1 && tmp.x+mx[i] <= n && tmp.y+my[i] >= 1 && tmp.y+my[i] <= n){
Q.push(Node(tmp.x+mx[i],tmp.y+my[i],tmp.step+1));
}
}
}
}
bool cmp(Edge a,Edge b){
return a.length < b.length;
}
int main(){
int i,j,k;
scanf("%d",&t);
for(i=1;i<=t;i++){
int hcnt = 0,gcnt = 0;
memset(maph,0,sizeof(maph));
memset(map,0,sizeof(map));
edges.clear();
for(j=0;j<M;j++){
connect[j].clear();
}
scanf("%d",&n);
getchar();
//輸入
for(j=1;j<=n;j++){
for(k=1;k<=n;k++){
scanf("%c",&map[j][k]);
if(map[j][k] == 'G'){
gcnt++;
}
if(map[j][k] == 'H'){
hcnt++;
maph[j][k] = hcnt;
}
}
getchar();
}
int cnt = 0;
for(j=1;j<=n;j++){
for(k=1;k<=n;k++){
if(map[j][k] == 'G'){
cnt++;
memset(mem,0,sizeof(mem));//清空記錄
bfs(j,k,cnt);
}
}
}
sort(edges.begin(),edges.end(),cmp);
int ans = -1;
for(j=0;j<edges.size();j++){
connect[edges[j].h].push_back(edges[j].g);
memset(match,-1,sizeof(match));
int res = 0;
for(k=1;k<=hcnt;k++){
memset(used,0,sizeof(used));
if(canfound(k)){
res++;
}
}
if(res == hcnt){
ans = edges[j].length;
break;
}
}
if(ans != -1){
printf("Case %d: %d\n",i,ans);
}else{
printf("Case %d: Vuter Dol Kupokat\n",i);
}
}
return 0;
}