蓝桥杯2012Java组决赛(九宫重排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重要的是状态转移,保存下一步所有状态。

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

猜你喜欢

转载自blog.csdn.net/weixin_43752167/article/details/92618426