网易_地牢逃脱 bfs广度优先搜索

本文介绍了一款名为“网易_地牢逃脱”的游戏算法。玩家需要在给定的地牢地图中,利用特定的步长移动,寻找最坏情况下逃离地牢所需的最多步数。文章详细解释了解题思路,并提供了一段Java实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网易_地牢逃脱

题目描述

给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指定的步长遍历地牢,要求每一步都不可以超过地牢的边界,也不能到达障碍上。地牢的出口可能在任意某个可以通行的位置上。牛牛想知道最坏情况下,他需要多少步才可以离开这个地牢。

输入描述:

每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 50),表示地牢的长和宽。接下来的 n 行,每行 m 个字符,描述地牢,地牢将至少包含两个 '.'。接下来的一行,包含两个整数 x0, y0,表示牛牛的出发位置(0 <= x0 < n, 0 <= y0 < m,左上角的坐标为 (0, 0),出发位置一定是 '.')。之后的一行包含一个整数 k(0 < k <= 50)表示牛牛合法的步长数,接下来的 k 行,每行两个整数 dx, dy 表示每次可选择移动的行和列步长(-50 <= dx, dy <= 50)

输出描述:

输出一行一个数字表示最坏情况下需要多少次移动可以离开地牢,如果永远无法离开,输出 -1。以下测试用例中,牛牛可以上下左右移动,在所有可通行的位置.上,地牢出口如果被设置在右下角,牛牛想离开需要移动的次数最多,为3次。

示例1

输入

3 3

...

...

...

0 1

4

1 0

0 1

-1 0

0 -1

输出

3

题意:

这道题主要是理解题意,开始完全没看懂,后来看了看大佬的分析,才明白怎么回事

题目先是输入迷宫的参数,然后起点位置,然后k种走的方法,每一步都得在这k种走法中找。题目说:地牢的出口可能在任意某个可以通行的位置上。牛牛想知道最坏情况下,他需要多少步才可以离开这个地牢。意思是出口可以再任何一个位置,然后找到这个位置走的最短步数,然后从这些最短步数中找最大值。

做法:最容易的是用bfs,直接寻找从起点开始算可以走的最长步数,每走一个点就标记已经走过,最后输出最大值就行。但是请注意,题目说的是出口可以在任意一个位置的最坏情况。那么当有一个点为“.”时,而且没法到达这个点,那么结果输出为-1

import java.util.*;
public class Main {
   
   
    public static int dx[]=new int[52];
    public static int dy[]=new int[52];
    public static int m;
    public static int n;
    public static void main(String args[]) {     
        int i,j,k,d;
        int a,b;
        Scanner cin=new Scanner(System.in);
        int start;
        


        while(cin.hasNextInt()) {
            n=cin.nextInt();
            m=cin.nextInt();
            char[][]mmap=new char[n][m];
            int[][]vis=new int[n][m];
            for(i=0;i<n;i++){
               mmap[i]=cin.next().toCharArray();
            }
            int startx=cin.nextInt();
            int starty=cin.nextInt();
            k=cin.nextInt();
            //System.out.println(k);
            for(j=0;j<k;j++)
            {
                dx[j]=cin.nextInt();
                dy[j]=cin.nextInt();
            }

            class Node{
                int x;
                int y;
         
                Node(int x, int y){
                    this.x = x;
                    this.y = y;
                }
         
                public Node getK(int k){//尝试走第K种步子到达的节点
                    return new Node(x+dx[k],y+dy[k]);
                }
     
                public boolean isleagle(){//判断这个节点是不是在地牢内,是不是障碍
                    return x>=0&&y>=0&&x<n&&y<m&&mmap[x][y]=='.';
                }
            }
            Queue<Node>que=new LinkedList();
            while(!que.isEmpty())
            {
             que.poll();
                
            }
            
            vis[startx][starty]=1;
            Node startPoint=new Node(startx,starty);
            Node tmp,newPoint;
            que.add(startPoint);
            while(!que.isEmpty())
            {
            	tmp=que.poll();
            //	System.out.printf("%d %d\n",tmp.x,tmp.y);
            	for(i=0;i<k;i++){
            		newPoint=tmp.getK(i);
            		if(newPoint.isleagle()&&(vis[newPoint.x][newPoint.y]==0)){
            			vis[newPoint.x][newPoint.y]=vis[tmp.x][tmp.y]+1;
            			que.add(newPoint);
            		}
            	}
            }
            int ans=0;
            int flag=0;
            for(i=0;i<n;++i){
            	
            	for(j=0;j<m;++j)
            		{
            		if(mmap[i][j]=='.'&&vis[i][j]==0)flag=1;
            		ans=Math.max(ans, vis[i][j]);
            		
            		}
            	if(flag>0)break;
            }
            
//        for(i=0;i<n;++i){
//            	
//         for(j=0;j<m;++j)
//            		System.out.printf("%d ",vis[i][j]);
//            	System.out.println();
//            }
            if(flag>0)System.out.println(-1);
            else 
            {
                if(ans!=1)System.out.println(ans-1);
                else System.out.println(-1);	
            	
            }
     
      
             
        }
         
         
    }
     
     
 
}
/*
4 3
X.X
...
XXX
X.X
0 1
4
1 0
0 1
-1 0
0 -1

 */

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值