1. 程式人生 > >hdu 2364 Escape【模擬優先隊列】【bfs】

hdu 2364 Escape【模擬優先隊列】【bfs】

昨天 php char style sin std turn 存在 -1

http://acm.hdu.edu.cn/showproblem.php?pid=2364

題意:從唯一的起點‘@’出發,輸出到達邊界的步數,如果不能到達,輸出-1。每走下一步,優先選擇轉彎的方向,只能直走(兩邊都是障礙物)時,才選擇直走方向,重點是,不能往回走。

判斷能否下一步轉彎的思路是:先將四個方向用0,1,2,3標記,如果當前步方向和下一步方向相等,當前步方向+1,方向-1,如果這兩個方向上同時存在障礙物,說明只能直走,加入隊列;如果當前步方向和下一步方向不相等時,直接加入隊列。這道題我理解錯一個地方,它走過的地方其實可以再走,只是,走過的方向不能再走,所以當我用二維數組標記該點是否走過時,是有問題滴,因為它直接就將四個方向都標記為已經走過,正解應該是,在二維基礎上多加一維,用以標記該點的四個方向。

~~~這道題,為什麽我先判斷只能直走的情況,再判斷轉彎的情況呢~~因為我對 c++的優先隊列並不熟悉,就在函數內部直接判斷的時候模擬優先隊列操作過程,如果不用優先隊列,直接用if(nowq.father!=i)Q.push(nextq);會將除了往回走的方向以外的三個方向直接無序加入,而此題的要求是,優先轉彎,不能轉彎再直走。

ps:昨天本來想把這道題作為我的雙十一大禮包的,結果寫了一個下午,都沒有寫出來,自己好菜啊~~~

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace
std; #define N 85 int map[N][N],mmin,flag,n,m,vis[N][N][4]; char str[N][N]; typedef struct node{ int x,y; int father;//記錄方向 int step;//記錄步數 }node; int bfs(int x,int y) { int k[4][2]={0,1,-1,0,0,-1,1,0}; int nx,ny,xi,yi,x1,y1,x2,y2; node nextq,nowq; memset(vis,0,sizeof
(vis));//初始化標記數組 queue<node>Q; flag = 0;//標記是否能夠成功到達 nowq.father = -1;//起點的方向是-1,區別其它點 nowq.x = x; nowq.y = y; nowq.step = 0;//初始化起點 vis[x][y][0]=1,vis[x][y][1]=1;//起點標記為已經走過 vis[x][y][2]=1,vis[x][y][3] = 1; Q.push(nowq);//將起點加入隊列 while(!Q.empty()) { nowq = Q.front() ; Q.pop(); if(nowq.x == 0||nowq.y == 0||nowq.x == n-1||nowq.y == m-1)//到達出口 { if(str[nowq.x][nowq.y]!=#) flag = 1;//能夠成功到達 return nowq.step ; } for(int i = 0; i < 4; i ++) { nx = nowq.x + k[i][0]; ny = nowq.y + k[i][1]; if(nx < 0||ny < 0||nx > n-1||ny > m-1||str[nx][ny]==#||vis[nx][ny][i]) continue; //不能越界,不能是墻,不能已經是訪問過的點 nextq.x = nx; nextq.y = ny; nextq.father = i;//記錄父點到當前點的方向 nextq.step = nowq.step + 1;//步數加1 if(nowq.father%2 == i%2) { if(nowq.father == i) { x1 = nowq.x + k[(i+1)%4][0]; y1 = nowq.y + k[(i+1)%4][1]; x2 = nowq.x + k[(i-1+4)%4][0]; y2 = nowq.y + k[(i-1+4)%4][1]; if(str[x1][y1]!=.&&str[x2][y2]!=.)//如果當前位置左右兩邊都不能走即只能直走 { vis[nx][ny][i] = 1;//標記該方向為已經訪問過 Q.push(nextq); } } } else { vis[nx][ny][i] = 1; Q.push(nextq); } } } return -1; } int main() { int t,i,j,x,y; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(str,0,sizeof(str)); for(i = 0; i < n; i ++) { scanf("%s",str[i]); for(j = 0; j < m; j ++) { if(str[i][j] == @)//找到起點,存入x,y. { x = i; y = j; } } } mmin = bfs(x,y);//返回步數 if(flag)//如果能到達出口。輸出步數 printf("%d\n",mmin); else printf("-1\n"); //否則輸出-1 } return 0; }

hdu 2364 Escape【模擬優先隊列】【bfs】