1.迷宫寻路
题目描述
假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N 后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
输出描述:
路径的长度,是一个整数
示例1
输出
7
思路:用BFS, 创建类,成员中包含坐标,携带的钥匙,在这个坐标是第几步 三个信息。 其中钥匙的字母不超过26,INT的位数超过26,
所以可以用一位int值的位运算保存持有的钥匙, 用三维数组,标识 此状态下(钥匙持有状态)是否走过此坐标。
需要注意的地方: Scanner 的 nextLine() 要提前多用一次吃点回车,或者用next()一个一个录入
不要搞混 行于列 的关系 = =
static int min=999999;
static char[][] map=new char[110][110];
static int next[][]={{1,0},{-1,0},{0,1},{0,-1}};
static int m,n;
static int [][][] visit = new int[110][110][1500];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
m=sc.nextInt();
n=sc.nextInt();
sc.nextLine();
for(int i=0;i<m;i++) {
map[i] = sc.nextLine().toCharArray();
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(map[i][j]=='2'){
System.out.println(bfs(i,j));
return;
}
}
}
}
static int bfs(int x,int y){
/**
* 首先拿到入口,压入queue
* 开始判空que循环,
* 用next数组,做循环判断四个方向,越界continue
* 是出口,返回node.step +1
* 是小写,用(1<<char-'a')| node.k ,存储钥匙
* 是大写,判断有没有钥匙,没钥匙continue
* 判断可走,在三维数组中写为1
* 并将新构建Node(携带最新的key,并step+1)压入queue
*/
LinkedList<Node> queue= new LinkedList<>();
queue.offer(new Node(x,y,0,0));
while(queue.size()>0){
Node t= queue.poll();
//System.out.println(" "+t.x+","+t.y+" ->"+t.k+" ===="+t.step);
for(int k=0;k<4;k++){
int mx = t.x+next[k][0];
int my = t.y+next[k][1];
int key=t.k;
if(mx<0||mx>=n||my<0||my>=m||map[mx][my]=='0')
continue;
if(map[mx][my]=='3')return t.step+1;
if(map[mx][my]>='A'&&map[mx][my]<='Z'){
int o=map[mx][my]-'A';
if((key&(1<<o))==0)continue;
}
if(map[mx][my]>='a'&&map[mx][my]<='z'){
key=(1<<map[mx][my]-'a')|key;
}
if(visit[mx][my][key]==0) {
visit[mx][my][key] = 1;
queue.offer(new Node(mx,my,key,t.step+1));
}
}
}
return -1;
}
public static class Node {
int x, y, k, step;
public Node(int x, int y, int k, int step) {
this.x = x;
this.y = y;
this.k = k;
this.step = step;
}
}
2.推箱子游戏
有一个推箱子的游戏, 一开始的情况如下图:
上图中, '.' 表示可到达的位置, '#' 表示不可到达的位置,其中 S 表示你起始的位置, 0表示初始箱子的位置, E表示预期箱子的位置,你可以走到箱子的上下左右任意一侧, 将箱子向另一侧推动。如下图将箱子向右推动一格;
..S0.. -> ...S0.
注意不能将箱子推动到'#'上, 也不能将箱子推出边界;
现在, 给你游戏的初始样子, 你需要输出最少几步能够完成游戏, 如果不能完成, 则输出-1。
输入描述:
第一行为2个数字,n, m, 表示游戏盘面大小有n 行m 列(5< n, m < 50);
后面为n行字符串,每行字符串有m字符, 表示游戏盘面;
输出描述:
一个数字,表示最少几步能完成游戏,如果不能,输出-1;
输入例子1:
3 6 .S#..E .#.0.. ......
输出例子1:
11
思路:BFS,与上题不同的是,上题需要记录的“状态”是钥匙的携带情况,此题的“状态”是“箱子的位置”,(即状态相同的情况下,
走过的位置不饿能再走)
每次判断移动后是否到了箱子的位置,如果是,则箱子也被推动,保存刷新的状态。
如果不是,则进行普通的保存
如果状态箱子的位置等于出口,则返回结果
import java.util.*;
public class Main {
static char[][] map=new char[110][110];
static int next[][]={{1,0},{-1,0},{0,1},{0,-1}};
static int m,n;
static int [][][][] visit = new int[60][60][60][60];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n=sc.nextInt();
m=sc.nextInt();
sc.nextLine();
for(int i=0;i<n;i++) {
map[i] = sc.nextLine().toCharArray();
}
int r1=0,r2=0,b1=0,b2=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(map[i][j]=='S') {
r1 = i;
r2 = j;
}
if(map[i][j]=='0'){
b1=i;
b2=j;
}
}
}
System.out.println(bfs(r1,r2,b1,b2));
}
static int bfs(int r1,int r2,int b1,int b2){
LinkedList<Node> queue=new LinkedList<>();
queue.offer(new Node(r1,r2,b1,b2));
visit[r1][r2][b1][b2]=1;
while(queue.size()>0){
Node t= queue.poll();
if(map[t.bx][t.by]=='E'){
return visit[t.x][t.y][t.bx][t.by]-1;
}
for(int k=0;k<4;k++){
int mx=t.x+next[k][0];
int my=t.y+next[k][1];
//System.out.println(mx+" ---- "+my);
if(mx<0||mx>=n||my<0||my>=m||map[mx][my]=='#')continue;
if(mx==t.bx&&my==t.by){
int mbx=t.bx+next[k][0];
int mby=t.by+next[k][1];
if(mbx>=n||mbx<0||mby<0||mby>=m
||map[mbx][mby]=='#'||visit[mx][my][mbx][mby]!=0)continue;
visit[mx][my][mbx][mby]= visit[t.x][t.y][t.bx][t.by]+1;
queue.offer(new Node(mx,my,mbx,mby));
}else{
if(visit[mx][my][t.bx][t.by]!=0)continue;
visit[mx][my][t.bx][t.by] = visit[t.x][t.y][t.bx][t.by]+1;
queue.offer(new Node(mx,my,t.bx,t.by));
}
}
}
return -1;
}
public static class Node {
int x, y, bx, by;
public Node(int x, int y, int bx, int by) {
this.x = x;
this.y = y;
this.bx = bx;
this.by = by;
}
}
}