1.迷宫寻路
题目描述
假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N 后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
输出描述:
路径的长度,是一个整数
示例1
输入
5 5 02111 01a0A 01003 01001 01111
输出
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) { map[i] = sc.nextLine().toCharArray(); } for(int i=0;i){ for(int j=0;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<*/ LinkedList ; } if(map[mx][my]>='a'&&map[mx][my]<='z'){ key=(1<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< continue
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) { map[i] = sc.nextLine().toCharArray(); } int r1=0,r2=0,b1=0,b2=0; for(int i=0;i){ for(int j=0;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 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; } } }