九宫重排_康拓展开_bfs
历届试题 九宫重排
时间限制:1.0s 内存限制:256.0MB
问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
![](https://images2015.cnblogs.com/blog/1098952/201703/1098952-20170329203242467-794003050.png)
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
123.46758
样例输出
3
样例输入
13524678.
46758123.
46758123.
样例输出
22
拿到这个题的时候没什么思路,之前也做过bfs的题,最大的问题在于状态的保存,后来看到有个编码题用到了康拓展开,豁然开朗,数学真的是奇妙啊!还有很多不知道的东西呢!
又知道了java的几个坑,哪怕是数组直接赋值也是赋的地址,添加到链表之类的也是地址,想要不受干扰只能手工拷贝。
1 package study_code; 2 3 import java.util.LinkedList; 4 import java.util.Queue; 5 import java.util.Scanner; 6 7 public class 八数码 { 8 9 static int[] vis = new int [900900]; //判断哈希值是否被访问 10 static int[] f = new int[9]; //保存阶乘 11 static int end; //最终状态的哈希值 12 static node start = new node(); 13 static String resPath; 14 static int[][] dir = {{-1,0},{1,0},{0,-1},{0,1}}; 15 static char[] dirc = {'U','D','L','R'}; 16 static class node{ 17 int loc; //记录当前空格位置 用一个数字记录 1-9 18 int s[]; //记录当前所有数字的位置 19 int hashVal; //当前状态的哈希值 20 String path = ""; //记录当前路径 21 public node() { 22 } 23 } 24 25 public static void fac() { 26 f[0] = 1; 27 for (int i = 1; i < f.length; i++) { 28 f[i] = f[i-1] * i; 29 } 30 } 31 32 //康拓展开 33 public static int getHash(int[] s) { 34 int res = 0; 35 for (int i = 0; i < s.length; i++) { 36 int index =0; 37 for (int j = i+1; j < s.length; j++) { 38 if (s[j]<s[i]) { 39 index++; 40 } 41 } 42 res += index*f[9-1-i]; 43 } 44 return res; 45 } 46 47 48 public static boolean bfs() { 49 Queue<node> q = new LinkedList<node>(); 50 q.offer(start); 51 vis[start.hashVal] = 1; 52 while (!q.isEmpty()) { 53 node cur = q.poll(); 54 vis[cur.hashVal] = 1; 55 if (cur.hashVal == end) { 56 resPath = cur.path; 57 return true; 58 } 59 int x =cur.loc/3; 60 int y =cur.loc%3; 61 for (int i = 0; i < 4; i++) { 62 int tx = x + dir[i][0]; 63 int ty = y + dir[i][1]; 64 if (tx<0||ty<0||tx>=3||ty>=3) { 65 continue; 66 } 67 node temp = new node(); 68 temp.loc = tx*3+ty; 69 temp.path = cur.path+dirc[i]; 70 temp.s = cur.s.clone(); 71 //交换空格的位置 72 temp.s[cur.loc] = temp.s[temp.loc]; 73 temp.s[temp.loc] = 0; 74 75 temp.hashVal = getHash(temp.s); 76 if (vis[temp.hashVal] == 1) { 77 continue; 78 } 79 q.offer(temp); 80 vis[temp.hashVal] = 1; 81 } 82 } 83 return false; 84 85 86 87 } 88 public static void main(String[] args) { 89 Scanner sc = new Scanner(System.in); 90 fac(); 91 String t = sc.nextLine(); 92 char[] c = t.toCharArray(); 93 int[] n = new int[c.length]; 94 for (int i = 0; i < c.length; i++) { 95 if (c[i] == '.') { 96 n[i] = 0; 97 start.loc = i; 98 }else { 99 n[i] = c[i] - '0'; 100 } 101 } 102 start.s = n.clone(); 103 start.hashVal = getHash(start.s); 104 t = sc.nextLine(); 105 c = t.toCharArray(); 106 n = new int[c.length]; 107 for (int i = 0; i < c.length; i++) { 108 if (c[i] == '.') { 109 n[i] = 0; 110 }else { 111 n[i] = c[i] - '0'; 112 } 113 } 114 end = getHash(n); 115 bfs(); 116 System.out.println(resPath.length()); 117 } 118 }