HDU 1043 Eight(八数码)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

 

Problem Description - 题目描述

  The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:
-puzzle有着超过100年的历史;就算没听过,估计也见过。它由15片滑块组成,各块标有数字1到15,并且全都装在一个4 x 4的边框里,防止哪块突然丢了。空块为’x’;这道题的目标是排列滑块使之顺序如下:

CN

 1  2  3  4
5 6 7 8
9 10 11 12
13 14 15 x
 

  where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

唯一的合法操作是将’x’与其共边的滑块交换。例子如下,通过一系列移动解决一个被稍微打乱的问题。

CN

 1  2  3  4     1  2  3  4     1  2  3  4     1  2  3  4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->

  The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.

  Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).

  In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three arrangement.

上一行的字母表示每次’x’与哪块相邻的滑块交换;有效值'r','l','u' 和 'd'分别表示右、左、上、下。

并非所有情况都有解;在1870年,一个叫Sam Loyd的人就以发布了一个无解版本而出名,成功地难住了许多人。实际上,要制造无解的情况只需交换两个滑块(当然是非’x’滑块)。

这个问题中,你需要写个程序解决著名的八数码问题,滑块为三行三列。

CN

Input - 输入

  You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle

1 2 3

x 4 6

7 5 8

  is described by this list:

1 2 3 x 4 6 7 5 8

你会得到若干个八数码的配置描述。每个描述都是一个滑块初始位置的列表,从上往下,从左往右,使用数字1到8,还有’x’表示。比如,

x   

描述如下:

   x     

CN

Output - 输出

  You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
如果无解,输出”unsolvable''”,否则输出一个仅由'r', 'l', 'u' 和 'd' 组成的字符串,描述求解的步骤。这个字符串不含空格且单独在一行。用例间别输出空行。

CN

Sample Input - 输入样例

2  3  4  1  5  x  7  6  8

Sample Output - 输出样例

ullddrurdllurdruldr

题解
  逼你学新知识系列……(某废渣作死爆内存了……)
  状态可以用全排列表示,用康托展开来压缩状态和去重,然后剩下的只有BFS了……(无聊用了树状数组求逆序数)
  多组输入有点坑……其实如果符合情况直接输出空行也是可以的。

代码 C++

 #include <cstdio>
#include <cstring>
#include <queue>
#define MX 362880
#define bitMX 10 int tre[bitMX];
int lowBit(int a) { return -a&a; }
void add(int i) {
while (i < bitMX) { ++tre[i]; i += lowBit(i); }
}
int sum(int i) {
int opt = ;
while (i) { opt += tre[i]; i -= lowBit(i); }
return opt;
} int ktf[], data[];
int preKte() {
int i, j, opt = ;
memset(tre, , sizeof tre);
for (i = ; ~i; --i) {
opt += sum(data[i])*ktf[i];
add(data[i]);
}
return opt;
}
void kte(int a) {
int i, j, tmp[];
for (i = ; i < ; ++i) tmp[i] = i + ;
for (i = ; i < ; ++i) {
j = a / ktf[i]; a %= ktf[i];
data[i] = tmp[j];
memcpy(tmp + j, tmp + j + , sizeof(int)*( - j));
}
data[i] = tmp[];
} int lst[MX];
char pre[MX];
void push(int now, int i, int j, char c, std::queue<int> &q) {
data[i] ^= data[j]; data[j] ^= data[i]; data[i] ^= data[j];
int nxt = preKte();
if (!pre[nxt]) {
lst[nxt] = now; pre[nxt] = c;
q.push(nxt);
}
data[i] ^= data[j]; data[j] ^= data[i]; data[i] ^= data[j];
}
void init() {
int i, j, now, nxt;
ktf[] = ;
for (i = , j = ; ~i; --i, ++j) ktf[i] = ktf[i + ] * j;
memset(lst, -, sizeof lst);
lst[] = ; pre[] = ' ';
std::queue<int> q; q.push();
while (!q.empty()) {
now = q.front(); q.pop();
kte(now);
for (i = ; data[i] != ; ++i);
if (i > ) push(now, i, i - , 'd', q);
if (i < ) push(now, i, i + , 'u', q);
if (i % ) push(now, i, i - , 'r', q);
if ((i + ) % ) push(now, i, i + , 'l', q);
} }
int main() {
init();
int i, j;
char red[];
while (gets(red)) {
for (i = j = ; i < ; i += , ++j) data[j] = red[i] == 'x' ? : red[i] - '';
if (~lst[i = preKte()]) {
for (j = i; j; j = lst[j]) putchar(pre[j]);
puts("");
}
else puts("unsolvable");
}
return ;
}

HDU 1043 Eight(八数码)的更多相关文章

  1. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  2. Hdu 1043 Eight (八数码问题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目描述: 3*3的格子,填有1到8,8个数字,还有一个x,x可以上下左右移动,问最终能否移动 ...

  3. hdu 1043 Eight (八数码问题)【BFS】+【康拓展开】

    <题目链接> 题目大意:给出一个3×3的矩阵(包含1-8数字和一个字母x),经过一些移动格子上的数后得到连续的1-8,最后一格是x,要求最小移动步数. 解题分析:本题用BFS来寻找路径,为 ...

  4. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

  5. 【双向广搜+逆序数优化】【HDU1043】【八数码】

    HDU上的八数码 数据强的一B 首先:双向广搜 先处理正向搜索,再处理反向搜索,直至中途相遇 visit 和 队列都是独立的. 可以用一个过程来完成这2个操作,减少代码量.(一般还要个深度数组) 优化 ...

  6. hdu 1043 Eight 经典八数码问题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 The 15-puzzle has been around for over 100 years ...

  7. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  8. HDU 1043 Eight (BFS&#183;八数码&#183;康托展开)

    题意  输出八数码问题从给定状态到12345678x的路径 用康托展开将排列相应为整数  即这个排列在全部排列中的字典序  然后就是基础的BFS了 #include <bits/stdc++.h ...

  9. HDU 1043 八数码(A*搜索)

    在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...

随机推荐

  1. 剪格子---(dfs回溯)

    如图p1.jpg所示,3 x 3 的格子中填写了一些整数. 我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以 ...

  2. itoa()函数

    itoa()函数 itoa():char *itoa( int value, char *string,int radix); 原型说明: value:欲转换的数据.string:目标字符串的地址.r ...

  3. UI自动化框架——构建思维

    目的:从Excel中获取列的值,传输到页面 技巧:尽可能的提高方法的重用率 Java包: 1.java.core包 3个类:1)日志(LogEventListener)扩展web driver自带的事 ...

  4. Linux之SSH免密登录

    实验方法: 开启两台虚拟机A和B,IP地址分别为192.168.222.12.192.168.222.10 在虚拟机A下做如下操作,生成公钥和密钥: [root@localhost ~]# ssh-k ...

  5. DOIS 2019 DevOps国际峰会北京站来袭~

    DevOps 国际峰会是国内唯一的国际性 DevOps 技术峰会,由 OSCAR 联盟指导.DevOps 时代社区与高效运维社区联合主办,共邀全球80余名顶级专家畅谈 DevOps 体系与方法.过程与 ...

  6. OAuth2认证和授权:ResourceOwnerPassword认证

    ResourceOwnerPassword在 ClientCredentials认证上新增了用户名和密码 但通过RequestPasswordTokenAsync获取不到refresh_token,不 ...

  7. Python之猴子补丁

    1.在运行时,对属性,方法,函数等进行动态替换 2.其目的往往是为了通过替换,修改来增强,扩展原有代码的能力 #test2.py class Person: def get_score(self): ...

  8. OpenStack-Neutron-VPNaaS-配置

    配置openstack版本:Juno vpnaas配置的资料很少,官网目前参考的https://wiki.openstack.org/wiki/Neutron/VPNaaS/HowToInstall比 ...

  9. 【转】jira插件Zephyr的具体使用

    在工作中,我们通常是在excel表格中编写测试用例,增删改查功能都不错,但保存.管理.共享都不完美,为了让公司领导或其他同事方便查看测试执行情况和测试进度,我们引入了TestLink工具来编写测试用例 ...

  10. 通用订单搜索的API设计得失录

    先把 Joshua Bloch 大神的 API PDF 放在这里膜拜下:"How to Design a Good API and Why it Matters.pdf" 总述 在 ...