历届试题 九宫重排  
时间限制: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());
}
}

九宫重排_康拓展开_bfs的更多相关文章

  1. 九宫重拍(bfs + 康拓展开)

    问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12 ...

  2. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  3. 【康拓展开】及其在求全排列第k个数中的应用

    题目:给出n个互不相同的字符, 并给定它们的相对大小顺序,这样n个字符的所有排列也会有一个顺序. 现在任给一个排列,求出在它后面的第i个排列.这是一个典型的康拓展开应用,首先我们先阐述一下什么是康拓展 ...

  4. ACM/ICPC 之 BFS(离线)+康拓展开(TSH OJ-玩具(Toy))

    祝大家新年快乐,相信在新的一年里一定有我们自己的梦! 这是一个简化的魔板问题,只需输出步骤即可. 玩具(Toy) 描述 ZC神最擅长逻辑推理,一日,他给大家讲述起自己儿时的数字玩具. 该玩具酷似魔方, ...

  5. ACM/ICPC 之 BFS(离线)+康拓展开 (HDU1430-魔板)

    魔板问题,一道经典的康拓展开+BFS问题,为了实现方便,我用string类来表示字符串,此前很少用string类(因为不够高效,而且相对来说我对char数组的相关函数比较熟),所以在这里也发现了很多容 ...

  6. nyoj 139 我排第几个--康拓展开

    我排第几个 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 现在有"abcdefghijkl”12个字符,将其所有的排列中按字典序排列,给出任意一种排列,说 ...

  7. bnuoj 1071 拼图++(BFS+康拓展开)

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=1071 [题意]:经过四个点的顺逆时针旋转,得到最终拼图 [题解]:康拓展开+BFS,注意先预处理,得 ...

  8. hdu 1043 pku poj 1077 Eight (BFS + 康拓展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://poj.org/problem?id=1077 Eight Time Limit: 1000 ...

  9. 8数码,欺我太甚!<bfs+康拓展开>

    不多述,直接上代码,至于康拓展开,以前的文章里有 #include<iostream> #include<cstdio> #include<queue> using ...

随机推荐

  1. matlab中padarray函数在numpy、python中的实现

    a = np.arange(6) a = a.reshape((2, 3)) print np.lib.pad(a, 1, 'symmetric') 运行结果: [[ ] [ ] [ ] [ ]]

  2. css隐藏元素的六类13种方法

    隐藏元素的方法 隐藏元素的方法可以总结为六类:直接隐藏.对溢出内容隐藏.对元素透明度进行调整.将元素移除当前屏幕.对元素的层级关系进行调整.对元素进行裁剪 只有对元素的透明度进行调整才可以点击,其余都 ...

  3. git常用命令(三)

    ====================================================================== 本地仓库操作 ====================== ...

  4. youku服务端

    文件结构 config import os IP_PORT = () BACKLOG = BASE_DIR = os.path.dirname(os.path.dirname(__file__)) B ...

  5. tomcat7下载地址

    tomcat7下载地址:https://tomcat.apache.org/download-70.cgi

  6. 采坑笔记——mysql的order by和limit排序问题

    背景说明 今天写出一个十分弱智的bug,记录一下,提醒自己以后别这种犯错,不怕丢人哈~ 在写一个分页查询记录的sql时,要根据添加的时间逆序分页输出,之前的写法是酱紫 select record.a, ...

  7. RedHat6.4安装图形行化界面

    1.1    打开电源进入RedHat shell命令行界面 1.2    查看系统镜像包括的所有软件包组信息 [root@zhongyi-test ~]# yum grouplist Loaded ...

  8. Pagehelper介绍

    本文引自:https://my.oschina.net/zudajun/blog/745232 摘要: com.github.pagehelper.PageHelper是一款好用的开源免费的Mybat ...

  9. JAVA / MySql 编程—— 第一章 数据库的设计

     1.        数据库设计:将数据库中的数据实体及这些数据实体之间的关系进行规划和结构化的过程: 良好的数据库设计: 节省数据的存储空间 能够保证数据的完整性 方便进行数据库应用系统的开发 糟糕 ...

  10. CERC2017 F: Faulty Factorial 简单数论题

    #include <iostream> using namespace std; #define ll long long ; ll n,p,r; ll poww(ll a,ll b){ ...