蓝桥杯历届试题 九宫重排(BFS)



问题描述:

如下面第一个图的九宫格中,放着 1~8
的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

在这里插入图片描述
在这里插入图片描述

我们把第一个图的局面记为:12345678.   把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。 输入格式
  输入第一行包含九宫的初态,第二行包含九宫的终态。 输出格式   输出最少的步数,如果不存在方案,则输出-1。

样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22

解题思路:

  使用广度搜索,不断移动为空的格子。找到符合条件的字符串时就是最少的步骤。之所以是最少是因为BFS遍历的特性。
  需要注意的是在遍历的过程中会出现重复的字符串,需要跳过,否则会超时。

代码实现:

package 历届试题;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
    
    
	
	static String star;
	static String end;
	static LinkedList<Move> list = new LinkedList<Move>(); //用于bfs的队列
	static HashSet<String> set = new HashSet<String>();
	
	public static void main(String[] args) {
    
    
		Scanner scanner = new Scanner(System.in);
		star = scanner.next();
		end = scanner.next();
		System.out.println(bfs());
	}

	private static int bfs() {
    
    
		int[] dx = {
    
    -1,0,1,0};   //上,左,下,右
		int[] dy = {
    
    0,-1,0,1};
		int sx = star.indexOf(".")/3;   //寻找九宫格初始状态空格子的位置
		int sy = star.indexOf(".")%3;
		list.add(new Move(sx,sy,star,0));
		while(!list.isEmpty()) {
    
    
			Move move = list.pollFirst();
			if(move.temp.equals(end)) {
    
      //达到了目标状态
				return move.step;
			}
			for(int i=0; i<4; i++) {
    
    
				int x = move.x + dx[i];
				int y = move.y + dy[i];
				if(x<3 && x>=0 && y<3 && y>=0) {
    
      //保证不出界
					//将两个位置进行交换
					String t = move.temp;
					char c = t.charAt(x*3+y);
					t = t.replace(c, '-');
					t = t.replace('.', c);
					t = t.replace('-', '.');
					if(!set.contains(t)) {
    
      //为了提高效率,添加过的字符串进行跳过
						list.add(new Move(x, y, t, move.step+1));
						set.add(t);
					}
				}
			}
		}
		return -1;
	}
}

class Move {
    
    
	int x;    //x和y表示空格所在的坐标
	int y;
	String temp;   //当前格子的状态
	int step;   //当前的步数
	
	public Move(int x, int y, String temp, int step) {
    
    
		super();
		this.x = x;
		this.y = y;
		this.temp = temp;
		this.step = step;
	}
}

提交结果:
在这里插入图片描述
第二次提交是跳过重复字符串的优化,第一次是没跳过重复字符串的代码。可以一下内存消耗相差了四倍。

猜你喜欢

转载自blog.csdn.net/HC199854/article/details/109585212