1. 程式人生 > 其它 >POJ 3083 Children of the Candy Corn

POJ 3083 Children of the Candy Corn

題意

給你一個迷宮,要求輸出靠左牆走,靠右牆走和最短的路徑長度。

分析

最短的路徑直接bfs就行了,就不多嗶嗶了。

因為題目保證S與E將始終位於迷宮邊緣之一,而不是角落,所以我們可以確定他面朝的方向。

靠左牆走即先考慮他面朝方向的左邊,如果不行,就順時針遍歷一下,找到最早的可行的方向。

而靠右牆走即先考慮他面朝方向的右邊,如果不行,就逆時針遍歷一下,找到最早的可行的方向。

舉個栗子,一開始你要走左邊,發現左邊有牆,這時,我們應該優先考慮前面,這樣才是靠左走。

每次走過來的方向即為面向的方向,再根據上述描述來做即可,方向搞對至關重要。

詳細情況請見程式碼

#include<cstdio>
#include
<algorithm> #include<cstring> using namespace std; int n,m,T,d; char a[55][55]; int dx[4]={-1,0,1,0}; int dy[4]={0,1,0,-1}; //方向要按一定順序,要麼順時針,要麼逆時針 int vis[55][55]; struct obj{ int x,y; int tot; }q[2005]; void bfs(int x,int y){ //bfs求最短路 vis[x][y]=1; int head=1,tail=0; q[++tail].x=x; q[tail].y
=y; q[tail].tot=1; while(head<=tail){ for(int i=0;i<4;i++){ int xx=q[head].x+dx[i]; int yy=q[head].y+dy[i]; if(a[xx][yy]=='#'||vis[xx][yy]||xx<=0||xx>n||yy<=0||yy>m) continue; q[++tail].x=xx; q[tail].y=yy; q[tail].tot
=q[head].tot+1; vis[xx][yy]=1; if(a[xx][yy]=='E'){ printf("%d\n",q[tail].tot); return ; } } head++; } return ; } int dfsl(int x,int y,int dir,int cnt){ //靠左牆走 dir表示面朝方向 if(a[x][y]=='E') return cnt; int k=dir-1; if(k==0) k=4; for(int i=0;i<4;i++){ if(k==5) k=1; int xx=x+dx[k-1]; int yy=y+dy[k-1]; if(xx<=0||xx>n||yy<=0||yy>m||a[xx][yy]=='#'){ k++; //方向順時針轉 continue; } return dfsl(xx,yy,k,cnt+1); } } int dfsr(int x,int y,int dir,int cnt){ //靠右牆走 dir表示面朝方向 if(a[x][y]=='E') return cnt; int k=dir+1; if(k==5) k=1; for(int i=0;i<4;i++){ if(k==0) k=4; int xx=x+dx[k-1]; int yy=y+dy[k-1]; if(xx<=0||xx>n||yy<=0||yy>m||a[xx][yy]=='#'){ k--; //方向逆時針轉 continue; } return dfsr(xx,yy,k,cnt+1); } } int main(){ scanf("%d",&T); while(T--){ memset(vis,0,sizeof(vis)); memset(q,0,sizeof(q)); scanf("%d%d",&m,&n); for(int i=1;i<=n;i++) scanf("%s",a[i]+1); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(a[i][j]=='S'){ if(i==n) d=1; else if(j==m) d=4; else if(i==1) d=3; else if(j==1) d=2; //分析面朝方向 1表示朝北,2表示朝東,3表示朝南,4表示朝西 printf("%d ",dfsl(i,j,d,1)); printf("%d ",dfsr(i,j,d,1)); bfs(i,j); } } } } return 0; }