lightoj 1150 - Ghosts! 【BFS + 二分查找 + 判二分图完美匹配】

来源:互联网 发布:中日贸易数据 编辑:程序博客网 时间:2024/06/05 22:26
1150 - Ghosts!
PDF (English)StatisticsForum
Time Limit: 2 second(s)Memory Limit: 32 MB

It's a dark, cloudy and spooky night. The ghosts of 'VutPara' graveyard have awakened. They are planning to take revenge against humans. They are dead but the humans are alive that's their main headache. So, they want to frighten all the people nearby.

'Vutpara' can be described as an n x n grid. Each cell can be one of the following types:

'.' - The cell is empty

'G' - The cell contains a ghost

'H' - The cell contains a human

'#' - The cell contains over-polluted air, the ghosts can't fly over this cell

The ghosts can move vertically or horizontally but not diagonally. And they can fly to any cell if the air is not over-polluted. It takes one minute to move to an adjacent cell. And it takes two minutes to frighten a human if the ghost is flying over the human (means that the position of the ghost and the human is same). But the ghosts are quite lazy, so any ghost can frighten at most one human. And after their work is done they want to go back to their grave (Initial position).

The night is getting over and they have a little time left. As they are smart enough they know all the human positions and the map. Now they want to frighten all the humans in the map using minimum time.

Input

Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case starts with a blank line and an integer n (5 ≤ n ≤ 25). Then n lines follow. Each of the line contains n characters each describing 'Vutpara'. You can assume that number of ghosts is always greater than or equal to the number of humans and the number of ghosts is no more than 50. And there is at least one human in the map.

Output

For each case of input, print the case number and the minimum time needed to frighten all the people or 'Vuter Dol Kupokat' if it's not possible to frighten all the people.

Sample Input

Output for Sample Input

4

 

8

....##..

.....#..

..#...G.

G...####

H#..HG.G

#....#.#

H.#G..H.

..##...#

 

6

......

G.....

......

......

......

.....H

 

6

.....G

.H....

......

......

....H.

G.....

 

6

#.#G#.

G....#

G..##.

H###.#

...#H#

..#GHH

Case 1: 12

Case 2: 20

Case 3: 12

Case 4: Vuter Dol Kupokat

 


PROBLEM SETTER: JANE ALAM JAN


题意:有一个n*n的地图,图中有4种字符。'#'表示此处不能过,'G'表示一个幽灵,'H'表示一个人,'.'表示此处可以过,幽灵每走一步需要1单位时间。已知每个幽灵最多针对一个人且需要花费2个单位时间,幽灵是十分聪明的。现在问你所有人会不会全部被针对,若会输出幽灵完成这一切所需的最少时间(加上幽灵回到初始位置的时间),否则输出Vuter Dol Kupokat。


思路:BFS预处理图的最短路,然后枚举时间值mid,根据mid值建二分图,判能否完美匹配。



AC代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define MAXN 60#define INF 0x3f3f3f3fusing namespace std;int dist[MAXN][MAXN][MAXN];int N, M;//幽灵数 人数struct perfectmatch{    int Map[MAXN][MAXN];    bool used[MAXN];    int match[MAXN];    int DFS(int x)    {        for(int i = 1; i <= N; i++)        {            if(Map[x][i] && !used[i])            {                used[i] = true;                if(match[i] == -1 || DFS(match[i]))                {                    match[i] = x;                    return 1;                }            }        }        return 0;    }    bool judge()    {        int ans = 0;        memset(match, -1, sizeof(match));        for(int i = 1; i <= M; i++)        {            memset(used, false, sizeof(used));            ans += DFS(i);        }        return ans == M;    }}PM;int n; char str[MAXN][MAXN];struct rec{    int x, y;    int step;};rec g[MAXN], h[MAXN];void getMap(){    scanf("%d", &n);    N = M = 0;    for(int i = 0; i < n; i++)    {        scanf("%s", str[i]);        for(int j = 0; j < n; j++)        {            if(str[i][j] == 'G')                g[++N].x = i, g[N].y = j;            if(str[i][j] == 'H')                h[++M].x = i, h[M].y = j;        }    }}void new_map(int mid){    memset(PM.Map, 0, sizeof(PM.Map));    for(int i = 1; i <= M; i++)        for(int j = 1; j <= N; j++)            if(dist[i][g[j].x][g[j].y] <= mid)                PM.Map[i][j] = 1;}bool vis[MAXN][MAXN];bool Can(rec a){    return a.x >= 0 && a.x < n && a.y >= 0 && a.y < n && str[a.x][a.y] != '#' && !vis[a.x][a.y];}void BFS(int id, int sx, int sy){    memset(vis, false, sizeof(vis));    int Move[4][2] = {0,1, 0,-1, 1,0, -1,0};    queue<rec> Q;    rec now, next;    now.x = sx, now.y = sy, now.step = 0;    Q.push(now);    while(!Q.empty())    {        now = Q.front();        Q.pop();        dist[id][now.x][now.y] = now.step;        for(int k = 0; k < 4; k++)        {            next.x = now.x + Move[k][0];            next.y = now.y + Move[k][1];            if(Can(next))            {                next.step = now.step + 1;                vis[next.x][next.y] = true;                Q.push(next);            }        }    }}int k = 1;void solve(){    memset(dist, INF, sizeof(dist));    for(int i = 1; i <= M; i++)        BFS(i, h[i].x, h[i].y);    int l = 0, r = 1200, mid;    int ans = INF;    while(r >= l)//二分    {        mid = (l + r) >> 1;        new_map(mid);        if(PM.judge())//完美匹配            ans = mid, r = mid - 1;        else            l = mid + 1;    }    printf("Case %d: ", k++);    if(ans == INF)        printf("Vuter Dol Kupokat\n");    else        printf("%d\n", ans * 2 + 2);}int main(){    int t;    scanf("%d", &t);    while(t--)    {        getMap();        solve();    }    return 0;}


0 0
原创粉丝点击