迷宫寻路(BFS、Java实现)

题目

假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙

输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N
后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。

输出描述:
路径的长度,是一个整数

示例1
输入
5 5
02111
01a0A
01003
01001
01111

输出
7

题解

每一步的状态包含当前坐标、已有门的钥匙、路径长度。
其中已有门的钥匙就两种情况:有或没有,那么不妨用二进制表示是否有。
(key&(1<<(ch-‘a’))==1表示key有a的钥匙。

然后考虑选用队列还是优先队列。根据队列先进先出的原理,排在队首的路径长度一定最小,故可以不要用优先队列进行重载优先级。

最后进行剪枝,一个位置可以走多次,但是同样key状态时走多次肯定其长度会大于第一次走。即vis[x][y][key]==1时,应剪枝掉。

代码

import java.io.*;
import java.math.*;
import java.util.*;



public class Main{
	static class node {
		int x,y,key,sum;
		public node(int x,int y,int key,int sum) {
			this.x=x;
			this.y=y;
			this.key=key;
			this.sum=sum;
		}
	}
	
	
    public static String []g=new String[107];
    public static int N,M;
    
    public static void main(String[] args){
    	Scanner in=new Scanner(System.in);
        N=in.nextInt();
        M=in.nextInt();
        for(int i=0;i<N;i++){
            g[i]=in.next();
        }
        int u=-1,v=0;
        for(int i=0;i<N;i++) {
        	String tmp=g[i];
        	for(int j=0;j<tmp.length();j++) {
        		if(tmp.charAt(j)=='2') {
        			u=i;
        			v=j;
        			break;
        		}
        	}
        	if(u!=-1) break;
        }
        System.out.println(bfs(u,v));
    }
    
    private static int bfs(int u,int v){
        Queue<node> que=new LinkedList();
        int [][]dir={{0,1},{0,-1},{-1,0},{1,0}};
        int [][][]vis=new int[107][107][1025];
        node tmp=new node(u,v,0,0);
        que.offer(tmp);
        vis[u][v][0]=1;
        
        while(!que.isEmpty()) {
        	tmp=que.poll();
        	int x=tmp.x;
        	int y=tmp.y;
        	int key=tmp.key;
        	int sum=tmp.sum;
        	if(g[x].charAt(y)=='3') return sum;
        	
        	for(int i=0;i<4;i++) {
        		int fx=x+dir[i][0];
        		int fy=y+dir[i][1];
        		
        		if(fx<0 || fx>=N || fy<0 || fy>=M) continue;
        		char ch=g[fx].charAt(fy);
        		if(ch=='0') continue;
        		if(ch>='A' && ch<='Z') {
        			if((key&(1<<(ch-'A')))==0) {
        				continue;
        			}
        		}
        		int now=0;
        		if(g[fx].charAt(fy)<='z' && g[fx].charAt(fy)>='a') {
        			now=1<<(g[fx].charAt(fy)-'a');
        		}
        		if(vis[fx][fy][key|now]==0) {
        			vis[fx][fy][key|now]=1;
        			que.offer(new node(fx,fy,key|now,sum+1));
        		}
        		
        	}
        }
        return -1;
    }
}
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页