hdu3085雙向bfs+曼哈頓距離判斷

Last night, little erriyue had a horrible nightmare. He dreamed that he and his girl friend were trapped in a big maze separately. More terribly, there are two ghosts in the maze. They will kill the people. Now little erriyue wants to know if he could find his girl friend before the ghosts find them.
You may suppose that little erriyue and his girl friend can move in 4 directions. In each second, little erriyue can move 3 steps and his girl friend can move 1 step. The ghosts are evil, every second they will divide into several parts to occupy the grids within 2 steps to them until they occupy the whole maze. You can suppose that at every second the ghosts divide firstly then the little erriyue and his girl friend start to move, and if little erriyue or his girl friend arrive at a grid with a ghost, they will die.
Note: the new ghosts also can devide as the original ghost.
Input
The input starts with an integer T, means the number of test cases.
Each test case starts with a line contains two integers n and m, means the size of the maze.
The next n lines describe the maze. Each line contains m characters. The characters may be:
‘.’ denotes an empty place, all can walk on.
‘X’ denotes a wall, only people can’t walk on.
‘M’ denotes little erriyue
‘G’ denotes the girl friend.
‘Z’ denotes the ghosts.
It is guaranteed that will contain exactly one letter M, one letter G and two letters Z.
Output
Output a single integer S in one line, denotes erriyue and his girlfriend will meet in the minimum time S if they can meet successfully, or output -1 denotes they failed to meet.

題目大意:
男盆友和女盆友同時困在一個迷宮內,男的一次可以走三步,女的一次走一步,迷宮內還有兩個魔鬼並且還會分身,牆以及有魔鬼的地方不可以走,但是魔鬼可以走牆,並且分身後的魔鬼還可以繼續分身,問兩人是否可以相遇;可以就輸出最短的時間;
思路:
1,由於要判斷兩人是否可以相遇,我們就用雙向bfs,要做到從兩個人同時開始搜索,則需要設置一個全局step記錄步數,只要進行了搜索,次序隨便,就改變時間,自然就可以看做是同時進行的了;
2,由於題目說,可以看做魔鬼先走然後人再走,所以我們先加上時間,在來搜索。對於魔鬼,它可以走牆所在的位置,這個條件很關鍵,這決定了我們是否可以用曼哈頓距離來判斷魔鬼是否走到當前的位置,而不用再來模擬魔鬼的走向;
3,還有一點就是,上次搜索的時候符合條件的點,這一次搜索不一定就符合了,因爲,在每一秒的行走過程中,我們看成是魔鬼先走,人然後再走;
4,至於怎麼實現男的一秒走三步,女的一秒走一步,那就是函數的調用次數問題了。而且在每一次搜索的時候,我們是將隊列中的所有點全部拿出來進行擴展,這樣就可以保證隊列中的點的詢問時間是一致的,也就是它們都是在同一步擴展出來的;

#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn=805;
char mp[maxn][maxn];
bool vis[2][maxn][maxn];
int step,mx,my,gx,gy;
int z[2][2],cnt;
int flag=0;
struct node
{
    int x,y;
    node(int a=0,int b=0)
    {
        x=a,y=b;
    }
};
queue<node> q[2];
int dx[]= {0,0,-1,1};
int dy[]= {1,-1,0,0};
bool check(int who,int x,int y)
{
    return x>=0&&x<n&&y>=0&&y<m&&abs(x-z[0][0])+abs(y-z[0][1])>step*2&&abs(x-z[1][0])+abs(y-z[1][1])>step*2&&mp[x][y]!='X';
}
int bfs(int who)
{
    int sz=q[who].size();
    while(sz--)
    {
        node tmp=q[who].front();
        q[who].pop();
        if(!check(who,tmp.x,tmp.y)) continue;
        for(int i=0; i<4; i++)
        {
            int xx=tmp.x+dx[i];
            int yy=tmp.y+dy[i];
            if(check(who,xx,yy)&&vis[who][xx][yy]==false)
            {
                if(vis[1-who][xx][yy])
                {
                    flag=1;
                    return 1;
                }
                vis[who][xx][yy]=true;
                q[who].push(node(xx,yy));
            }
        }
    }
    return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        step=0,cnt=0,flag=0;
        memset(vis,false,sizeof vis);
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
        {
            scanf("%s",mp[i]);
            for(int j=0; j<m; j++)
            {
                if(mp[i][j]=='M')
                    mx=i,my=j;
                if(mp[i][j]=='G')
                    gx=i,gy=j;
                if(mp[i][j]=='Z')
                    z[cnt][0]=i,z[cnt][1]=j,cnt++;
            }
        }

        while(!q[0].empty()) q[0].pop();
        while(!q[1].empty()) q[1].pop();
        q[0].push(node(mx,my));
        q[1].push(node(gx,gy));
        vis[0][mx][my]=vis[1][gx][gy]=1;
        while(!q[0].empty()||!q[1].empty())
        {
            step++;
            if(bfs(0)) break;
            if(bfs(0)) break;
            if(bfs(0)) break;
            if(bfs(1)) break;
        }
        if(flag)
            printf("%d\n",step);
        else
            puts("-1");
    }
    return 0;
}
發佈了174 篇原創文章 · 獲贊 64 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章