洛谷P1301 魔鬼之城(bfs基礎)
阿新 • • 發佈:2018-12-16
題目連結 在一個被分割為N*M個正方形房間的矩形魔鬼之城中,一個探險者必須遵循下列規則才能跳躍行動。他必須從(1, 1)進入,從(N, M)走出;在每一房間的牆壁上都寫了一個魔法數字,是1~13之內的自然數;探險者可以想像出8個方向中的任何一個(水平或垂直或對角線方向),隨後他就可以作一次空間跳躍穿過這一方向上的連續的X個房間,其中X是他原來所在房間的魔法數字。但如果在這一方向上的房間數小於X,則他不作任何跳躍,而必須想像另一個方向。同時,探險者不能作連續兩次相同方向的跳躍。
例如在上圖的5*4的魔鬼之城中,如果探險者現在所在的位置是(3, 3),那麼通過依次空間跳躍他可以到達下列房間中的一個:(1, 1),(3, 1),(1, 3),(5, 1),或(5, 3)。另外,如果他要用兩次跳躍從(5, 4)到達(3, 2),則他不能首先跳到(4, 3)(因為這樣他第二次跳躍的方向將和第一次相同,而這是不允許的)。所以他必須先跳躍到(2, 1)。
請你寫一個程式,對給定的地圖,算出探險者至少需要跳躍多少步才能離開魔鬼之城。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; int n,m,sq[105][105]; int dx[8]={-1,-1,0,1,1,1,0,-1}; int dy[8]={0,1,1,1,0,-1,-1,-1}; bool vis[105][105][10]; int ans[105][105]; struct node { int x,y,dir,sum; }q[100005];//接下來拓展的點的橫座標、縱座標、方向、步數 void bfs() { int head=1,tail=1; q[tail].x=1; q[tail].y=1; q[tail].dir=0; q[tail].sum=0; tail++; while(head<tail) { for(int k=0;k<8;k++) { if(k!=q[head].dir) { int nowx=q[head].x+dx[k]*sq[q[head].x][q[head].y]; int nowy=q[head].y+dy[k]*sq[q[head].x][q[head].y]; if(nowx<1 || nowx>n || nowy<1 || nowy>m) continue; if(!vis[nowx][nowy][k]) { vis[nowx][nowy][k]=1; ans[nowx][nowy]=q[head].sum+1; q[tail].x=nowx; q[tail].y=nowy; q[tail].dir=k; q[tail].sum=ans[nowx][nowy]; tail++; } if(ans[n][m]>0) return; } } head++; } } int main() { cin>>n>>m;//列、行 swap(n,m);//行、列 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>sq[i][j]; } bfs(); if(ans[n][m]>0) cout<<ans[n][m]<<endl; else cout<<"NEVER"<<endl; return 0; } /* int dfs(int x,int y,int sum) { if(sum>ans) return; if(x==n&&y==m) { ans=min(ans,sum); return; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=0;k<8;k++) { int nowx=x+dx[k]*sq[i][j]; int nowy=y+dy[k]*sq[i][j]; if(nowx<1 || nowx>n || nowy<1 || nowy>m) continue; if(!vis[nowx][nowy] && !flag[k]) { vis[nowx][nowy]=1; flag[k]=1; dfs(nowx,nowy,step+1); vis[nowx]][nowy]=1; flag[k]=0; } } flag[k]=0; return; }*/