地牢逃脱

Posted 千彧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了地牢逃脱相关的知识,希望对你有一定的参考价值。

题目描述

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

输入描述:

每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 50),表示地牢的长和宽。接下来的 n 行,每行 m 个字符,描述地牢,地牢将至少包含两个 ‘.‘。接下来的一行,包含两个整数 x
0
, y
0
,表示牛牛的出发位置(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
  1 import java.sql.Array;
  2 import java.util.ArrayList;
  3 import java.util.Arrays;
  4 import java.util.List;
  5 import java.util.Scanner;
  6 /**
  7  * 
  8  * 密室逃脱
  9  * @author Dell
 10  *
 11  */
 12 public class Main {
 13     
 14     
 15 static public int f() {
 16     /**
 17      * 
 18      *   输入数据
 19      */
 20     Scanner sc = new Scanner(System.in);
 21     int n = sc.nextInt();
 22     int m = sc.nextInt();
 23     sc.nextLine();
 24     String[][] map = new String[n][m];
 25     for (int i = 0; i < map.length; i++) {
 26         String s = sc.nextLine();
 27         map[i] = s.split("");
 28     }
 29 //    for (int i = 0; i < n; i++) {
 30 //        for (int j = 0; j < m; j++) {
 31 //            map[i][j] = sc.next();
 32 //        }
 33 //    }
 34     int x0 = sc.nextInt();
 35     int y0 = sc.nextInt();
 36     int k =  sc.nextInt();
 37     int[][] steps = new int [k][2];
 38     for (int i = 0; i < k; i++) {
 39         steps[i][0] = sc.nextInt();
 40         steps[i][1] = sc.nextInt();
 41     }
 42     
 43     
 44     int[][] stepNum = new int[n][m]; 
 45     for (int i = 0; i < n; i++) {
 46         for (int j = 0; j < m; j++) {
 47             stepNum[i][j] = -1; // -1 代表 还没访问 访问后会变成 步数
 48         }
 49     }
 50     stepNum[x0][y0] = 0;
 51     
 52     /**
 53      * 
 54      *  广度优先遍历
 55      *  
 56      */
 57     List<int[]> l1 = new ArrayList();
 58     List<int[]> l2 = new ArrayList();
 59     l1.add(new int[] {x0,y0});
 60     while(l1.size()>0) {
 61         l2 = new ArrayList();
 62         for (int[] point : l1) {
 63             for (int i = 0; i < steps.length; i++) {
 64                 int x= point[0]+steps[i][0];
 65                 int y= point[1]+steps[i][1];
 66                 if (x<0||x>n-1||y<0||y>m-1) {
 67                     continue;  // 越界 ,忽略此次移动
 68                 }
 69                 // 是否可达
 70                 boolean isReachable = map[x][y].equals(".");
 71                 // 是否被访问过
 72                 boolean isVisited = stepNum[x][y]==-1?false:true;
 73                 if (isReachable&&!isVisited) {
 74                     stepNum[x][y]=stepNum[point[0]][point[1]]+1;
 75                     l2.add(new int[] {x,y});
 76                 }
 77                 
 78             }
 79 //            l1.remove(point);
 80         }
 81             l1 = l2; // 将新一轮的点加入 赋给l1
 82     }
 83     // 遍历得到最大步数
 84     int max = 0;
 85         for (int i = 0; i < n; i++) {
 86             for (int j = 0; j < m; j++) {
 87                 if (map[i][j].equals(".")&&stepNum[i][j]==-1) {
 88                     return -1;  // 有-1不可达
 89                 }
 90                 if (stepNum[i][j]>max) {
 91                     max = stepNum[i][j];
 92                 }
 93                  
 94             }
 95         }
 96         return max;
 97 }    
 98 
 99 
100 public static void main(String[] args) {
101 int res = f();
102     System.out.println(res);
103 }    
104 
105 }

 



以上是关于地牢逃脱的主要内容,如果未能解决你的问题,请参考以下文章

双指针,BFS和图论

codecombat之边远地区的森林1-11关及地牢38关代码分享

SpriteKit游戏Delve随机生成地牢地图一个Bug的修复

网易极客战记官方攻略-地牢-健忘的宝石匠

网易极客战记官方攻略-地牢-注释中的密语

网易极客战记官方攻略-地牢-敌人的陷阱