注意:主类的名字必须是:Main,否则按无效代码处理。
思路:将九个格子按从上到下从左到右生成一个字符串,当某个格子为空(.)时,使用队列,按广度优先遍历的方法依次移动此时可以移动的格子,知道第一次找到目标字符串为止
package 历届国赛; import java.io.*; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Scanner; import java.util.List; public class 九宫重排 { static String yl,yh;//移动前和移动后的字符串 static int st = 0;//步数 static HashSet<String>hh = new HashSet();//记录递归中的字符串 static List<gz>list = new ArrayList(); static List<String>l = new ArrayList(); static int[][]w_m = {//当第n个格子为空时,哪个格子可以移动 {-1}, {2,4}, {1,3,5}, {2,6}, {1,5,7}, {2,4,6,8}, {3,5,9}, {4,8}, {5,7,9}, {6,8} }; static int move_num(String s){//哪个格子是空格 for(int i=0;i<s.length();i++){ if(s.charAt(i) == '.') return i+1; } return -1; } static String move(String y,int m,int n){//y为移动前,从m移动到n,返回移动后字符串 char[]c = y.toCharArray(); char mm = c[n-1]; c[n-1] = c[m-1]; c[m-1] = mm; return String.valueOf(c); } static class gz{//宫格类 int step;//步数 String now;//代表当前宫格的字符串 gz(int s,String n){ this.step = s; this.now = n; } } //用队列,当前空格位置,所有可移动的一次入队再出队,类似于广度优先遍历 static void bfs(){ hh.add(yl); gz g = new gz(0,yl); list.add(g);//将yl等所有的字符串封装进gz类(因为列表中每一步的步数值都必须独立) while(!list.isEmpty()){ gz now_ = list.remove(0);//取出第一个; if(now_.now.equals(yh)){ System.out.println(now_.step); break; } int n = move_num(now_.now); for(int i = 0;i<w_m[n].length;i++){//所有可以移动的格子 String temp = move(now_.now,w_m[n][i],n); if(!hh.contains(temp)){ int s = now_.step+1; gz g_ = new gz(s,temp); hh.add(temp); list.add(g_); } } } } public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc = new Scanner(System.in); yl = sc.next(); yh = sc.next(); bfs(); } }
