1. 程式人生 > >洛谷P1301 魔鬼之城(bfs基礎)

洛谷P1301 魔鬼之城(bfs基礎)

題目連結 在一個被分割為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;
}*/