1. 程式人生 > >HDU1728 逃離迷宮(BFS+思維)

HDU1728 逃離迷宮(BFS+思維)

 給定一個m × n (m行, n列)的迷宮,迷宮中有兩個位置,gloria想從迷宮的一個位置走到另外一個位置,當然迷宮中有些地方是空地,gloria可以穿越,有些地方是障礙,她必須繞行,從迷宮的一個位置,只能走到與它相鄰的4個位置中,當然在行走過程中,gloria不能走到迷宮外面去。令人頭痛的是,gloria是個沒什麼方向感的人,因此,她在行走過程中,不能轉太多彎了,否則她會暈倒的。我們假定給定的兩個位置都是空地,初始時,gloria所面向的方向未定,她可以選擇4個方向的任何一個出發,而不算成一次轉彎。gloria能從一個位置走到另外一個位置嗎?

Input

  第1行為一個整數t (1 ≤ t ≤ 100),表示測試資料的個數,接下來為t組測試資料,每組測試資料中, 
  第1行為兩個整數m, n (1 ≤ m, n ≤ 100),分別表示迷宮的行數和列數,接下來m行,每行包括n個字元,其中字元'.'表示該位置為空地,字元'*'表示該位置為障礙,輸入資料中只有這兩種字元,每組測試資料的最後一行為5個整數k, x 1, y 1, x 2, y 2 (1 ≤ k ≤ 10, 1 ≤ x1, x 2 ≤ n, 1 ≤ y 1, y 2 ≤ m),其中k表示gloria最多能轉的彎數,(x 1, y 1), (x 2, y2)表示兩個位置,其中x 1,x 2對應列,y 1, y 2對應行。 

Output

  每組測試資料對應為一行,若gloria能從一個位置走到另外一個位置,輸出“yes”,否則輸出“no”。

Sample Input

2
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
5 5
...**
*.**.
.....
.....
*....
2 1 1 1 3

Sample Output

no
yes

 

解題思路:

首先應該注意輸入的m和n。

 

逃離迷宮

分析:
圖中任意一個點都有3個狀態(x,y,cnt),cnt是目前的轉向次數。
假如說用BFS先向四周搜尋,那表示每個點的轉向次數是特別複雜的,那怎麼辦呢?解決方法是先沿著一個方向搜,一直搜到底,把中間符合要求的點加入到佇列中,這樣的話這一個方向上經過的合法點的轉向次數就是父點轉向+1。這樣就能很簡單的把圖中能經過的點的轉向次數表示出來了。如果在搜尋的過程中遇到了Goal,需要先判斷一下next.cnt<=k是否成立,如果next.cnt>k,很顯然不滿足題意,還需要嘗試能否通過其他路徑使得在轉向次數cnt<=k的情況下到達Goal,如果嘗試了所有的點都不可以,那就輸出no了。

注意:
1.因為從出發點選擇方向時是不算轉向次數的,所以s.cnt=-1
2.還有一個坑爹的地方,終點可能是牆'*',如果終點是牆無論如何也是到達不了的,直接no
3.如果目標點就是出發點,直接yes
4.輸入Maze時有的情況下需要注意吃掉空格

 

AC程式碼:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

int n,m,k;
int sx,sy,ex,ey;
char mp[110][110];
int book[110][110];
int nx[4][2]={0,1,0,-1,1,0,-1,0};

struct node
{
    int x,y,cnt;
};

node getnode(int x,int y,int cnt)
{
    node q;
    q.x=x;
    q.y=y;
    q.cnt=cnt;
    return q;
}

void bfs(int x,int y,int cnt)
{
    queue<node> q;
    q.push(getnode(x,y,cnt));
    while(!q.empty())
    {
        for(int i=0;i<4;i++)
        {
            int tx=q.front().x+nx[i][0];
            int ty=q.front().y+nx[i][1];
            while(tx>=0&&tx<m&&ty>=0&&ty<n&&mp[tx][ty]=='.')//一直按照一個方向走下去
            {
                if(book[tx][ty]==0)
                {
                    if(tx==ex&&ty==ey&&q.front().cnt+1<=k)
                    {
                        printf("yes\n");
                        return;
                    }
                    book[tx][ty]=1;
                    q.push(getnode(tx,ty,q.front().cnt+1));
                }
                tx=tx+nx[i][0];//此時隊首還沒有pop所以這條路上的cnt都是一樣的
                ty=ty+nx[i][1];
            }
        }
        q.pop();
    }
    printf("no\n");
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(book,0,sizeof(book));
        memset(mp,0,sizeof(mp));
        scanf("%d%d",&m,&n);
        for(int i=0;i<m;i++)
        {
            scanf("%s",mp[i]);
        }
        scanf("%d%d%d%d%d",&k,&sy,&sx,&ey,&ex);
        sx--;sy--;ex--;ey--;
        book[sx][sy]=1;
        if(sx==ex&&sy==ey) printf("yes\n");
        else if(mp[ex][ey]=='*') printf("no\n");
        else bfs(sx,sy,-1);
    }
    return 0;
}