迷宫寻路
题目:
假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N
后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
路径的长度,是一个整数。
5 5
02111
01a0A
01003
01001
01111
输出:7
前言
今天又是在图书馆学习的一天。同样地记录三件事吧
(1)今天邀请了大学的好朋友去看演出,已经买好票了,期待周日!!!
(2)今天红米发布k20和k20 pro了,感觉很不错,如果暑假实习能赚点钱就买一个!
思路
首先,定义一个类来表示二维数组中的每个位置点,每个点的属性有:x,y(理解为横纵坐标),key(表示拥有的钥匙),走的步数。
static class Node{
//x是纵坐标
int x;
//y是横坐标
int y;
int key;
int step;
public Node(int x,int y,int key, int step) {
this.x=x;
this.y=y;
this.key=key;
this.step=step;
}
}
之后采用广度优先搜索算法遍历二维数组,如果碰到钥匙,则用一个二进制数表示。优先表示的搜索的是最短的路径。
private static int bfs(int si, int sj, int n, int m, char[][] G) {
// TODO Auto-generated method stub
Queue<Node> queue=new LinkedList<>();
//表示二维数组的每一个节点的信息,这个信息是由两部分组成,位置和钥匙。
int [][][] mp=new int [101][101][1025];
//定义这个二维数组来表示当前位置的上下左右位置的数
int [][] next= {{-1,0},{0,-1},{1,0},{0,1}};
//向队列中添加位置点
queue.offer(new Node(si,sj,0,0));
while(!queue.isEmpty()) {
//取出队列的第一个元素
Node node=queue.poll();
for(int i=0;i<4;i++) {
//i=0表示当前位置的上面一个元素,等等
int x=node.x+next[i][0];
int y=node.y+next[i][1];
int key=node.key;
if(x<0||x>=n||y<0||y>=m||G[x][y]=='0')
continue;
else if(G[x][y]=='3')
return node.step+1;
//表示捡钥匙
else if(G[x][y]<='z'&&G[x][y]>='a')
key=key|(1<<(G[x][y]-'a'));
//表示门是否匹配钥匙
else if(G[x][y]<='Z'&&G[x][y]>='A'&&(key&(1<<(G[x][y]-'A')))==0)
continue;
//表示当前位置是否遍历过。
if(mp[x][y][key]==0) {
mp[x][y][key]=1;
queue.offer(new Node(x,y,key,node.step+1));
}
}
}
return -1;
}
完整代码
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class mianshiti5 {
//定义内部类
static class Node{
int x;
int y;
int key;
int step;
public Node(int x,int y,int key, int step) {
this.x=x;
this.y=y;
this.key=key;
this.step=step;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan=new Scanner(System.in);
//二维数组的列数
int n=scan.nextInt();
int m=scan.nextInt();
scan.nextLine();
char [][] G=new char [n][m];
for(int i=0;i<n;i++) {
G[i]=scan.nextLine().toCharArray();
}
//找出起点的位置
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
if(G[i][j]=='2') {
System.out.println(bfs(i,j,n,m,G));
return;
}
}
}
}
private static int bfs(int si, int sj, int n, int m, char[][] G) {
// TODO Auto-generated method stub
Queue<Node> queue=new LinkedList<>();
int [][][] mp=new int [101][101][1025];
//定义这个二维数组来表示当前位置的上下左右位置的数
int [][] next= {{-1,0},{0,-1},{1,0},{0,1}};
//向队列中添加位置点
queue.offer(new Node(si,sj,0,0));
while(!queue.isEmpty()) {
//取出队列的第一个元素
Node node=queue.poll();
for(int i=0;i<4;i++) {
int x=node.x+next[i][0];
int y=node.y+next[i][1];
int key=node.key;
if(x<0||x>=n||y<0||y>=m||G[x][y]=='0')
continue;
else if(G[x][y]=='3')
return node.step+1;
else if(G[x][y]<='z'&&G[x][y]>='a')
key=key|(1<<(G[x][y]-'a'));
else if(G[x][y]<='Z'&&G[x][y]>='A'&&(key&(1<<(G[x][y]-'A')))==0)
continue;
if(mp[x][y][key]==0) {
mp[x][y][key]=1;
queue.offer(new Node(x,y,key,node.step+1));
}
}
}
return -1;
}
}