蓝桥杯2012Java组决赛(九宫重排bfs)

博客围绕九宫格数字卡片移动问题展开,已知九宫初态和终态,求最少移动步数,无法到达则输出 -1。介绍了解题使用的BFS算法,强调BFS中状态转移、保存下一步状态的重要性,同时指出减枝和判重也十分关键。

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

我们把图1的局面记为:12345678.
把图2的局面记为:123.46758

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

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

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

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

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


import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;

public class lanqiao2012_final_4 {
	public static String Start;//开始的字符串
	public static String end;//结束的字符串
	public static int dep = 1;
	public static class Node{
		public Node(String str, int pos, int dep) {
			this.val = str;
			this.position = pos;
			this.depth = dep;
		}
		String val;//保存字符串
		
		int position; //保存'.'位置
		int depth;//保存深度
		@Override
		public String toString() {
			return "Node [val=" + val + ", position=" + position + ", depth="
					+ depth + "]";
		}	
	}
	public static String change(String str,int postion1,int postion2){
		StringBuilder sb  =  new StringBuilder(str);
		
		char ch1 = sb.charAt(postion1);
		char ch2 = sb.charAt(postion2);
		sb.setCharAt(postion2, ch1);
		sb.setCharAt(postion1, ch2);
		return sb.toString();
	}
	public static int bfs(String str){
		int len = str.length()-1;
		Queue<Node> que = new LinkedList<Node>();//创建一个队列 用来发曾经遍历过的状态
		HashSet<String> hs = new HashSet<String>();//创建一个hashset用来判断这个状态是否已经遍历过
		int pos = 0;
		for(int i=0;i<str.length();i++){//找到.的位置
			if(str.charAt(i)=='.'){
				pos = i;  
				break;      
			}
		}
		if(pos-3>=0){
			que.add(new Node(change(str,pos-3,pos),pos-3,dep));//保存交换后的字符,.的位置 深度
			hs.add(change(str,pos-3,pos));
		}
		if(pos+3<=len){
			que.add(new Node(change(str,pos+3,pos),pos+3,dep));//
			hs.add(change(str,pos+3,pos));
		}
		if(pos%3<2){
			que.add(new Node(change(str,pos+1,pos),pos+1,dep));
			hs.add(change(str,pos+1,pos));
		}
		if(pos%3==1||pos%3==2){
			que.add(new Node(change(str,pos-1,pos),pos-1,dep));
			hs.add(change(str,pos-1,pos));
		}
		
		while(!que.isEmpty()){//需要判断重复走过的路,减枝
			Node p  = que.poll();
			if(p.val.equals(end)) return p.depth;
			int ps = p.position;
			
			if(ps-3>=0){
				if(!hs.contains(change(p.val,ps-3,ps)))
				que.add(new Node(change(p.val,ps-3,ps),ps-3,p.depth+1));//保存交换后的字符,.的位置 深度
				
			}
			if(ps+3<=len){
				if(!hs.contains(change(p.val,ps+3,ps)))
				que.add(new Node(change(p.val,ps+3,ps),ps+3,p.depth+1));//
				
			}
			if(ps%3<2){
				if(!hs.contains(change(p.val,ps+1,ps)))
				que.add(new Node(change(p.val,ps+1,ps),ps+1,p.depth+1));
			
			}
			if(ps%3==1||ps%3==2){
				if(!hs.contains(change(p.val,ps-1,ps)))
				que.add(new Node(change(p.val,ps-1,ps),ps-1,p.depth+1));
			}
			
		}
		return -1;
	}
	
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		
		Start = s.nextLine();
		end = s.nextLine();
		System.out.println(bfs(Start));
	}
}

bfs重要的是状态转移,保存下一步所有状态。

减枝和判重也十分重要 慢慢学~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值