Lightoj 1150 Ghosts!(bfs+二分+二分图)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37943488/article/details/82491549

1150 - Ghosts!

    PDF (English) Statistics Forum
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

 


题目大意:给一个地图,有一些怪兽和人,每个怪兽都要去吓一个人,怪兽只能走上下左右四个方向,一个怪兽只会吓一个人,吓一个人要两分钟,走一个格子要1分钟,问最后吓完所有人要多久

首先对怪兽进行广搜,找出他们离每一个人的距离,然后存起来,考虑到怪兽吓人是同时进行的,在某一个时间一定是所有怪物都把人吓完了并回去了,所以我们就二分这个时间,在这个时间内如果可以完成这个任务,就连一条边,建起一个图,跑一遍匈牙利即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=710;
const int maxm=200010;
const int inf=0x3f3f3f3f;
typedef pair<int,int> P;
struct LDJ
{
    int x;
    int y;
    int step;
};
struct Node
{
    int to;
    int next;
}edge[maxm];
int n;
int cnt;
int head[maxn];
char map[30][30];
int num[30][30];
int dis[30][30];
bool vis[30][30];
int odd,even;
int dirx[]={0,1,0,-1};
int diry[]={1,0,-1,0};
int match[710];
bool match_vis[710];
vector<P> G[710];
void init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
    return;
}
void add(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    return;
}
void bfs(int x,int y)
{
    queue<LDJ> que;
    LDJ start;
    start.x=x;
    start.y=y;
    start.step=0;
    que.push(start);
    //memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    //dis[x][y]=0;
    vis[x][y]=true;
    while(!que.empty())
    {
        LDJ now=que.front();
        que.pop();
        int nowx=now.x;
        int nowy=now.y;
        for(int k=0;k<4;k++)
        {
            int nx=nowx+dirx[k];
            int ny=nowy+diry[k];
            if(nx>=1&&ny>=1&&nx<=n&&ny<=n&&!vis[nx][ny]&&map[nx][ny]!='#')
            {
                
                //dis[nx][ny]=dis[nowx][nowy]+1;
                vis[nx][ny]=true;
                LDJ tmp;
				tmp.x=nx;
				tmp.y=ny;
                tmp.step=now.step+1;
				que.push(tmp);
                if(map[nx][ny]=='H')
                {
                    G[num[x][y]].push_back(make_pair(num[nx][ny],tmp.step*2+2));
                }
            }
        }
    }
    return;
}
bool dfs(int node)
{
    for(int i=head[node];~i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(!match_vis[v])
        {
            match_vis[v]=true;
            if(match[v]==-1||dfs(match[v]))
            {
                match[v]=node;
                return true;
            }
        }
    }
    return false;
}
int hungry()
{
    int ans=0;
    memset(match,-1,sizeof(match));
    for(int i=1;i<=odd;i++)
    {
        memset(match_vis,false,sizeof(match_vis));
        if(dfs(i))
        {
            ans++;
        }
    }
    return ans;
}
void build(int limit)
{
    for(int i=1;i<=odd;i++)
    {
        int len=G[i].size();
        for(int j=0;j<len;j++)
        {
            P tmp=G[i][j];
            if(tmp.second<=limit)
            {
                add(i,tmp.first);
            }
        }
    }
    return;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int test;
    scanf("%d",&test);
    for(int cas=1;cas<=test;cas++)
    {
        odd=0;
        even=0;
        memset(num,0,sizeof(num));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",map[i]+1);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(map[i][j]=='G')
                {
                    num[i][j]=++odd;
                }
                if(map[i][j]=='H')
                {
                    num[i][j]=++even;
                }
            }
        }
        for(int i=0;i<=odd;i++)
        {
            G[i].clear();
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(map[i][j]=='G')
                {
                    bfs(i,j);
                }
            }
        }
        int left=0;
        int right=100000;
        int ans=-1;
        while(left<=right)
        {
            int mid=(left+right)>>1;
            init();
            build(mid);
            if(hungry()>=even)
            {
                ans=mid;
                right=mid-1;
            }
            else
            {
                left=mid+1;
            }
        }
        if(ans==-1)
		{
			printf("Case %d: Vuter Dol Kupokat\n",cas);
		}
		else
		{
			printf("Case %d: %d\n",cas,ans);
		}
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37943488/article/details/82491549
今日推荐