历届试题 九宫重排  
时间限制:1.0s   内存限制:256.0MB
      
问题描述
  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式
  输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
  输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22
 
 
拿到这个题的时候没什么思路,之前也做过bfs的题,最大的问题在于状态的保存,后来看到有个编码题用到了康拓展开,豁然开朗,数学真的是奇妙啊!还有很多不知道的东西呢!
又知道了java的几个坑,哪怕是数组直接赋值也是赋的地址,添加到链表之类的也是地址,想要不受干扰只能手工拷贝。

 package study_code;

 import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner; public class 八数码 { static int[] vis = new int [900900]; //判断哈希值是否被访问
static int[] f = new int[9]; //保存阶乘
static int end; //最终状态的哈希值
static node start = new node();
static String resPath;
static int[][] dir = {{-1,0},{1,0},{0,-1},{0,1}};
static char[] dirc = {'U','D','L','R'};
static class node{
int loc; //记录当前空格位置 用一个数字记录 1-9
int s[]; //记录当前所有数字的位置
int hashVal; //当前状态的哈希值
String path = ""; //记录当前路径
public node() {
}
} public static void fac() {
f[0] = 1;
for (int i = 1; i < f.length; i++) {
f[i] = f[i-1] * i;
}
} //康拓展开
public static int getHash(int[] s) {
int res = 0;
for (int i = 0; i < s.length; i++) {
int index =0;
for (int j = i+1; j < s.length; j++) {
if (s[j]<s[i]) {
index++;
}
}
res += index*f[9-1-i];
}
return res;
} public static boolean bfs() {
Queue<node> q = new LinkedList<node>();
q.offer(start);
vis[start.hashVal] = 1;
while (!q.isEmpty()) {
node cur = q.poll();
vis[cur.hashVal] = 1;
if (cur.hashVal == end) {
resPath = cur.path;
return true;
}
int x =cur.loc/3;
int y =cur.loc%3;
for (int i = 0; i < 4; i++) {
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if (tx<0||ty<0||tx>=3||ty>=3) {
continue;
}
node temp = new node();
temp.loc = tx*3+ty;
temp.path = cur.path+dirc[i];
temp.s = cur.s.clone();
//交换空格的位置
temp.s[cur.loc] = temp.s[temp.loc];
temp.s[temp.loc] = 0; temp.hashVal = getHash(temp.s);
if (vis[temp.hashVal] == 1) {
continue;
}
q.offer(temp);
vis[temp.hashVal] = 1;
}
}
return false; }
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
fac();
String t = sc.nextLine();
char[] c = t.toCharArray();
int[] n = new int[c.length];
for (int i = 0; i < c.length; i++) {
if (c[i] == '.') {
n[i] = 0;
start.loc = i;
}else {
n[i] = c[i] - '0';
}
}
start.s = n.clone();
start.hashVal = getHash(start.s);
t = sc.nextLine();
c = t.toCharArray();
n = new int[c.length];
for (int i = 0; i < c.length; i++) {
if (c[i] == '.') {
n[i] = 0;
}else {
n[i] = c[i] - '0';
}
}
end = getHash(n);
bfs();
System.out.println(resPath.length());
}
}

最新文章

  1. 二、JSP、servlet、SQL三者之间的数据传递(前台与后台数据交互)
  2. eclipse编辑jsp保存的时候特别卡解决办法
  3. C#自定义控件属性显示在属性面板中操作
  4. 手动建库时一个小错误:ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance
  5. 10个不太为人所知的,但实用的PHP函数
  6. redhat linux 安装mysql5.6.27
  7. HTTPS-SSL/TSL与SNI的关系以及同IP多域名虚拟主机的SSL/TSL认证
  8. Xen、Openvz、KVM有什么区别?
  9. iOS App转让流程
  10. MySQL加锁分析
  11. [Leetcode][Python]47: Permutations II
  12. 51nod 区间中第K大的数
  13. Spring在JSP页面使用ServletContext
  14. 使用sklearn进行数据挖掘-房价预测(1)
  15. 学习用java基于webMagic+selenium+phantomjs实现爬虫Demo爬取淘宝搜索页面
  16. Word+PS制作拼音表格
  17. ul li内的文字水平居中显示
  18. 接口list
  19. Codeforces Round #554 (Div. 2) B. Neko Performs Cat Furrier Transform(思维题+log2求解二进制位数的小技巧)
  20. appium:运行脚本时,报404的解决办法

热门文章

  1. mac home brew install go
  2. MCV 的几种表单提交方式
  3. 第17章 EXTI—外部中断/事件控制器—零死角玩转STM32-F429系列
  4. vue 城市搜索组件
  5. C编程经验总结4
  6. 通过tomcat配置访问本机资源
  7. Thymeleaf显示Map集合数据
  8. ARM S3C2440 时钟初始化流程
  9. 理解volatile与synchronized
  10. [CQOI2007]余数求和 (分块+数学