/*算法竞赛入门经典 :7.5.3 八数码问题
* 使用哈希表判重*/
import java.util.Arrays;
import java.util.Scanner;
public class EightData {
static final int MAXSTATE = 1000000;// 最大状态数
static final int MAXHASHSIZE = 1000003;// 哈希表长度
static final int[] dx = { -1, 1, 0, 0 };
static final int[] dy = { 0, 0, -1, 1 };
static int[] head = new int[MAXHASHSIZE];
static int[] next = new int[MAXHASHSIZE];
static int[][] st = new int[MAXSTATE][9];
static int[] dist = new int[MAXSTATE];// 记录距离
static int[] src = new int[9];//原状态
static int[] dest = new int[9];//目标状态
static int[] s = new int[9];
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
for (int i = 0; i < 9; i++) {
st[1][i] = src[i] = scanner.nextInt();
}
for (int i = 0; i < 9; i++) {
dest[i] = scanner.nextInt();
}
int ans = bfs();
if (ans > 0) {
System.out.println(dist[ans]);
} else {
System.out.println(-1);
}
}
}
private static int bfs() {
Arrays.fill(dist, 0);
Arrays.fill(head, 0);
int front = 1, rear = 2;
while (front < rear) {
s = st[front];
if (Arrays.equals(s, dest))// 找到 递归出口
return front;
int z = 0;
for (z = 0; z < 9; z++) {// 寻找当前状态中0的位置
if (s[z] == 0)
break;
}
int x = z / 3;
int y = z % 3;
for (int i = 0; i < 4; i++) {// 尝试向4个方向移动
int newX = x + dx[i];
int newY = y + dy[i];
int newZ = newX * 3 + newY;
if (newX >= 0 && newX < 3 && newY >= 0 && newY < 3) {// 移动合法
st[rear] = Arrays.copyOf(s, s.length);// 扩展新节点
st[rear][newZ] = 0;//把0移至新位置
st[rear][z] = s[newZ];//在原0位置上移入新值
dist[rear] = dist[front] + 1;// 更新新节点距离值
if (try_to_insert(rear))// 如果成功插入查找表,修改队尾指针
rear++;
}
}
front++;
}
return 0;
}
private static int hash(int[] state) {// 哈希函数
int v = 0;
for (int i = 0; i < 9; i++)
v = v * 10 + state[i];
return v % MAXHASHSIZE;
}
private static boolean try_to_insert(int r) {
int h = hash(st[r]);
int u = head[h];
while (u > 0) {//从表头开始查找链表
if (Arrays.equals(st[u], st[r]))//找到插入失败
return false;
u = next[u];
}
next[r] = head[h];//插入链表在表头
head[h] = r;
return true;
}
}
算法竞赛入门经典 7.5.3 八数码问题
最新推荐文章于 2022-10-21 12:43:55 发布