第四届蓝桥杯JavaB组国赛-九宫重排

题目描述

如图1的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。
在这里插入图片描述
与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成图2所示的局面。
在这里插入图片描述
  我们把图1的局面记为:12345678.
  把图2的局面记为:123.46758

显然是按从上到下,从左到右的顺序记录数字,空格记为句点。

本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

例如:
  输入数据为:
  12345678.
  123.46758
  则,程序应该输出:
  3

再如:
输入格式
  13524678.
  46758123.
  则,程序输出:
  22

资源约定:
  峰值内存消耗(含虚拟机) < 64M
  CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

思路:广度优先搜索BFS

首先,对于多种路径选择最短路径(最少次数),十分符合广度优先搜索。广度优先搜索会一步步遍历,当第一次搜索到,那么这一定是最短路径。
广度优先搜索一般使用队列存储需要搜索的节点,由于队列的性质,从队头弹出一个元素后,将这个元素的相邻的节点从队尾插入。如此循环,直到队列为空。

public class Main{
	static HashSet<String> set=new HashSet<>();
	static String s;
	static String answer;
	static char[] ch;
	
	public static void main(String[] args) 
	{
		Scanner in=new Scanner(System.in);
		s=in.next();
		answer=in.next();
		Node n=new Node(s, s.indexOf(".")+1,0);
		set.add(s);
		System.out.println(bfs(n));
	}
	
	public static int bfs(Node e)
	{
		Queue<Node> que=new LinkedList<>();
		String iString;
		que.add(e);
		Node t=null;
		while(!que.isEmpty())
		{
			t=que.poll();
			ch=t.s.toCharArray();
			if(t.pos-3>0)    //检查空格上面的元素
			{
				swap(t.pos,t.pos-3);
				iString=new String(ch);
				if(iString.equals(answer)) return t.swap_num+1;
				if(!set.contains(iString))
				{
					set.add(iString);
					que.add(new Node(iString, t.pos-3,t.swap_num+1));
				}
				swap(t.pos-3,t.pos);
			}
			
			if(t.pos%3!=0)   //检查空格右侧的元素
			{
				swap(t.pos,t.pos+1);
				iString=new String(ch);
				if(iString.equals(answer)) return t.swap_num+1;
				if(!set.contains(iString))
				{
					set.add(iString);
					que.add(new Node(iString, t.pos+1,t.swap_num+1));
				}
				swap(t.pos+1,t.pos);
			}
			
			if ((t.pos-1)%3!=0)   //检查空格左侧的元素
			{
				swap(t.pos,t.pos-1);
				iString=new String(ch);
				if(iString.equals(answer)) return t.swap_num+1;
				if(!set.contains(iString))
				{
					set.add(iString);
					que.add(new Node(iString, t.pos-1,t.swap_num+1));
				}
				swap(t.pos-1,t.pos);
			}
			
			if (t.pos+3<10)       //检查空格下面的元素
			{
				swap(t.pos,t.pos+3);
				iString=new String(ch);
				if(iString.equals(answer)) return t.swap_num+1;
				if(!set.contains(iString))
				{
					set.add(iString);
					que.add(new Node(iString, t.pos+3,t.swap_num+1));
				}
				swap(t.pos+3,t.pos);
			}
		}
		return -1;
	}
	public static void swap(int x,int y)
	{
		char t=ch[x-1];
		ch[x-1]=ch[y-1];
		ch[y-1]=t;
	}
	
	static class Node
	{
		String s;
		int pos;
		int swap_num;
		Node(String ss,int ppos,int num)
		{
			s=ss;
			pos=ppos;
			swap_num=num;
		}
	}
}

该代码参考:https://blog.csdn.net/weixin_41793113/article/details/89043983

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值