BFS-走迷宫和八数码-java实现
BFS
走迷宫
思路
对于所有边权都是1的时候,广搜能搜到最短路径,深搜一定能找到终点

用队列解决,while queue不空,把队头取出,然后扩展能走的方向(没超过边界,没遇到墙并且没走过)。
存储两个方位偏移量dx,dy,对应上(-1,0)下(1,0)左(0,-1)右(0,1)移动,然后挨个遍历存储能走到离起点的距离,输出到终点的最短距离d[n-1][m
-1]
代码
/**** 做这种题目的步骤(最短路问题)*1.创建两个存储,一个存储值,一个存储距离*2.然后首先将第一个点的位置存储的距离提前标注出来*3.然后弄两个方向变量用于上下左右前进int[] dx = {-1,0,1,0}, dy = {0,1,0,-1};*4.然后如果四个方向上的点没有超过边界,在结合实际情况有没有用过的点,* 判断能不能够进行前进,如果可以就进行前进存储其内容g跟距离d+1* 5.最后返回想要的最短值d;* **/import java.io.*;
public class Main{static int N = 110,hh,tt,n,m;static int[][] g = new int[N][N];//用来存储迷宫地图static int[][] d = new int[N][N];//用来存储走的距离static PII[] q = new PII[N*N];//用来放每个点的下标public static int bfs(){hh = 0 ; tt = -1; //队列的头节点=0,尾节点 = 0;d[0][0] = 0; // 我们首先站在的是第一个点,所以值距离设置为0q[++tt] = new PII(0,0); //然后将第一个点下标存入q队列中//利用向量的方法进行让他上下左右判断是否能够前进int[] dx = {-1,0,1,0};//上(-1,0) 下(1,0)int[] dy = {0,1,0,-1};//左(0,-1) 右(0,1)while(hh <= tt){PII t = q[hh++]; //每一次将头结点拿出来for(int i = 0 ; i < 4 ; i ++ ){//然后进行下一步要往哪里走,这里可能有多重选择可走int x = t.first + dx[i]; //这里进行x轴向量判断int y = t.second + dy[i];//这里进行y轴向量的判断//如果x,y满足在地图中不会越界,然后地图上的点g是0(表示可以走),//然后这里是没走过的距离d是-1;if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1){//将现在可以走的点(x,y)加上上一个点计数距离的点加上一,就是现在走到的点的距离d[x][y] = d[t.first][t.second] + 1;q[++tt] = new PII(x,y);//然后将这一个可以走的点存入队列尾}}}return d[n-1][m-1]; //最后返回的是地图走到尽头最后一个位置的位置统计的距离}public static void main(String[] args)throws IOException{BufferedReader re = new BufferedReader(new InputStreamReader(System.in));BufferedWriter wt = new BufferedWriter(new OutputStreamWriter(System.out));String[] s = re.readLine().split(" ");n = Integer.parseInt(s[0]);m = Integer.parseInt(s[1]);for(int i = 0 ; i < n ; i ++ ){String[] st = re.readLine().split(" ");for(int j = 0 ; j < m ;j ++ ){g[i][j] = Integer.parseInt(st[j]);d[i][j] = -1;}}System.out.println(bfs());wt.close();}
}
//这是一个用来存储两个坐标的类Pair
class PII{int first,second;public PII(int first,int second){this.first = first;this.second = second;}
}
八数码
思路
重点是把一串字符串s映射到像上面的地图一样的位置,x=len(s)/3,y=len(s)%3然后这里dist距离用Map<String,Integer> 存储
返回最终状态的dist
代码
import java.util.*;
public class Main{public static void swap(char[] arr,int x,int y){char temp = arr[x];arr[x] = arr[y];arr[y] = temp;}public static int bfs(String start ,String end){Map<String,Integer> map = new HashMap<>();// 用来存储每种方式走过的距离Queue<String> q = new LinkedList<>();//队列,用来存储内容q.offer(start);//将初试元素插入到队列的尾部map.put(start,0);//将初始状态的值对应map中value值对应0;表示还没有进行前进;int[] dx = {-1,0,1,0},dy = {0,1,0,-1};//表示前进方向;上下左右//如果队列不是空的继续循环while(!q.isEmpty()){String t = q.poll();//将队头元素返回并抛出int k = t.indexOf('x');//找到x再String中的下标int x = k / 3 ; int y = k % 3;//然后进行以为数组转化成二维的操作下标操作if(t.equals(end)) return map.get(t); //如果进行过程中跟结束end相同的就提前结束for(int i = 0 ; i < 4 ; i ++ ){//这里进行四种方案int a = x + dx[i],b = y + dy[i]; if(a >= 0 && a < 3 && b >= 0 && b < 3){ //如果这种情况没有超出边界//将这种情况的字符串转化成字符数组,能够有下标进行交换char[] arr = t.toCharArray(); //然后交换x跟没有超出边界的值进行交换,二维转成一维下标x*3+y;swap(arr, k, a * 3 + b);//然后将字符数组转化成字符串String str = new String(arr);if(map.get(str) == null){ //如果这种情况对应的value值是null,说明还没有走过map.put(str,map.get(t) + 1);//然后将这种情况对应进行上一步的距离加上1q.offer(str);//然后将新的情况插入到队尾中}}//思路://比如走到距离为2即第二步时候,上下左右四种情况都可行的情况下,将每一中情况都//插入到队列尾部,然后queue[] = {2[1],2[1],2[1],2[1],3[1],3[1],3[2],3[4]};//队列会执行从前面开始2执行完之后可能会有3种情况往队列尾插入,//然后这样依次每一层进行搜索遍历//因为步数小的都会先插入到队列中,队列原则"先进先出"原则,所以肯定会把所有的//第二步执行完之后才会执行前面第二步执行过程中产生的三步,然后一直执行到最后第n步}}return -1; //如果执行完之后没有结果,那么返回-1;}public static void main(String[] args){Scanner scan = new Scanner(System.in);String start = "";for(int i = 0 ; i < 9 ; i ++ ){String s = scan.next();start += s;}String end = "12345678x";System.out.println(bfs(start,end));}
}