蓝桥杯-(九宫重排-bfs)

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

我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
  输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
  输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22
思路:
建造一个picture类,里面用于存放每一步的状态,当前"."所在的位置,已经当前是第几步,之后使用linkedlist存放每一次的状态,当结束一个状态之后判断是否与目标状态相同,如果相同的话那么就是这个状态,输出结果。把那个”.“当做一个人,就类似于走迷宫。
注意点:
1、中间每一次都要记录状态,我使用了String进行记录,将当前的数组遍历一下转换成为一个String,如果数组唯一,状态可以定也是唯一的。
2、要知道bfs是一个扩散式的搜索,当从一个节点搜索的时候会搜索出其余方向的几种状态,但是当让一个picture对象出队的时候,记住每一次子对象都是需要使用父对象修改,也就是在父对象基础上进行修改,所以我在中间增加了一次的复制操作。
3、最后使用一个arraylist用于记录每一次出现的状态,如果当前这个状态已经出现过了,那么下一次就不需要在对他进行入队了,避免重复计算。
**总结:**一道题目如果是求最短次数,最短的状态变换,求到达状态,基本上你就是往bfs上面想。
代码:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;

public class 九宫重排 {
	public static String startString,endString;
	public static String shu[][] = new String[3][3];
	public static LinkedList<picture> list = new LinkedList<>();
	public static ArrayList<String> arrayList = new ArrayList<>();//用于判断之前是够走到过这种状态,如果有的话就不不走了。
	public static void main(String[] args) {
		Scanner input =new Scanner(System.in);
		startString =input.next();
		endString = input.next();
		int t =0;
		for (int i = 0; i < startString.length(); i++) {
			shu[t/3][t%3] = startString.substring(i,i+1);
			t++;
		} //用于将输入的数据转换成为数组
		bfs();

	}
	public static void bfs() {
		int p = startString.indexOf(".")/3;//用于确定点的位置
		int q = startString.indexOf(".")%3;
		list.addLast(new picture(p, q, 0, startString));
		arrayList.add(startString);
		while(!list.isEmpty()) {
			picture temporacy = list.removeFirst();//一定是要从开头移除,队列,先进先出,从尾部插入,从头部出来
			int next [][] = {{0,1},{1,0},{0,-1},{-1,0}};//分别模拟四个方向右边,下边,左边,上边
			int tx,ty;
			for (int i = 0; i < next.length; i++) {
				tx =temporacy.x + next[i][0];
				ty =temporacy.y+next[i][1];//tx ,ty 代表下一次想要进入的位置 x y代表的是原来.的位置
				if (tx >= 3 || ty >= 3 || tx < 0 || ty < 0 ) {
					continue;
				}
				String num [][] =new String[3][3];
				int t =0;
				for (int j = 0; j < temporacy.state.length(); j++) {
					num[t/3][t%3] = temporacy.state.substring(j,j+1);
					t++;
				}
				String lk = num[tx][ty];
				num[tx][ty] = ".";
				num[temporacy.x][temporacy.y] = lk;//用于交换位置
				String res = "";
				for (int j = 0; j < num.length; j++) {
					for (int k = 0; k < num.length; k++) {
						res +=num[j][k];
					}
				}
				//System.out.println(res);
				if (res.equals(endString)) {
					System.out.println(temporacy.count+1);
					return;
				}else {
					if (!arrayList.contains(res)) {
						arrayList.add(res);
						list.addLast(new picture(tx, ty,temporacy.count+1, res));
					}
				}

			}
		}
	}
}
class picture{//参数:包括当前的的状态,哪些变量一直在变需要记录,记录最后需要的答案
	int x;//表示当前的位置
	int y;
	int count;//表示当前已经走了几步
	String state;//表示当前的状态
	public  picture(int x,int y,int count,String state) {
		super();
		this.x = x;
		this.y=y;
		this.count = count;
		this.state = state;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WeChat098

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值