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; }