题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表。

  经典八数码问题,传说此题不做人生不完整,关于八数码的八境界:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html

  我自己是用哈希(康托展开) + BFS  + 打表过的,第三重境界。

  由于一些高级的搜索现在还没学,所以目前能升级的也就是用双向BFS来做了,等过几天有心情了来做。

  本文长期更新。


算法:  

  由于此题是求某个起始状态到“12345678X”的步骤,所以可以考虑先求出“12345678X”的所有变换的步骤,即打表预处理。

  这里要注意就是最后输出的时候,由于我们求得是逆序,所以要倒序输出,倒序输出的时候要注意'u'、'd'、'l'、'r'都应该颠倒过来,比如说你从A状态向上变换为B状态,这时你从B变为A就要向下变换。

  这里哈希还是用的康托展开,这个问题我在上一篇博客中有提到过。

BFS + 打表:

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define eps 1e-8
#define INF 1e8
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MOD = ;
const int maxn = ;
bool vis[maxn];
string ans[maxn];
int fac[]={ , , , , , , , , , }; int Cantor(string str)
{
int ret = ;
int n = str.size();
for(int i = ; i < n ; i++) {
int cnt = ;
for(int j = i ; j < n ; j++)
if(str[j] < str[i])
cnt++;
ret += cnt * fac[n - i - ];
}
return ret;
}
void move_Up(string &str , int pos)
{
swap(str[pos] , str[pos - ]);
}
void move_Down(string &str , int pos)
{
swap(str[pos] , str[pos + ]);
}
void move_Left(string &str , int pos)
{
swap(str[pos] , str[pos - ]);
}
void move_Right(string &str , int pos)
{
swap(str[pos] , str[pos + ]);
}
void BFS(string start)
{
memset(vis , , sizeof(vis));
queue <string> que;
que.push(start);
int x = Cantor(start);
vis[x] = ;
ans[x] = "";
int pos;
while(!que.empty()) {
string u = que.front();
que.pop();
int i = Cantor(u);
for(pos = ; pos < ; pos++)
if(u[pos] == 'x')
break; if(pos > ) {
string tmp = u;
move_Up(tmp , pos);
int k = Cantor(tmp);
if(!vis[k]) {
vis[k] = ;
que.push(tmp);
ans[k] = ans[i] + 'u';
}
}
if(pos < ) {
string tmp = u;
move_Down(tmp , pos);
int k = Cantor(tmp);
if(!vis[k]) {
vis[k] = ;
que.push(tmp);
ans[k] = ans[i] + 'd';
}
}
if(pos % != ) {
string tmp = u;
move_Left(tmp , pos);
int k = Cantor(tmp);
if(!vis[k]) {
vis[k] = ;
que.push(tmp);
ans[k] = ans[i] + 'l';
}
}
if(pos % != ) {
string tmp = u;
move_Right(tmp , pos);
int k = Cantor(tmp);
if(!vis[k]) {
vis[k] = ;
que.push(tmp);
ans[k] = ans[i] + 'r';
}
}
}
}
int main()
{
char ch[];
string start = "12345678x";
BFS(start);
while(gets(ch))
{
string str = "";
for(int i = ; ch[i] != '\0' ; i++) {
if(ch[i] == ' ')
continue;
else
str += ch[i];
}
int k = Cantor(str);
if(vis[k]) {
for(int i = ans[k].size() - ; i >= ; i--) {
if(ans[k][i] == 'u')
putchar('d');
else if(ans[k][i] == 'd')
putchar('u');
else if(ans[k][i] == 'l')
putchar('r');
else
putchar('l');
}
puts("");
} else {
cout << "unsolvable" << endl;
}
}
return ;
}

HDU1043 八数码(BFS + 打表)的更多相关文章

  1. hdu-1043(八数码+bfs打表+康托展开)

    参考文章:https://www.cnblogs.com/Inkblots/p/4846948.html 康托展开:https://blog.csdn.net/wbin233/article/deta ...

  2. 紫书p199 八数码(BFS,hash)

    八数码问题  紫书上的简单搜索  渣渣好久才弄懂 #include<cstdio> #include<cstring> using namespace std; const i ...

  3. code1225 八数码Bfs

    Bfs搜索 1.把棋盘直接作为状态: #include<iostream> #include<cstring> #include<queue> #include&l ...

  4. POJ1077 八数码 BFS

    BFS 几天的超时... A*算法不会,哪天再看去了. /* 倒搜超时, 改成顺序搜超时 然后把记录路径改成只记录当前点的操作,把上次的位置记录下AC..不完整的人生啊 */ #include < ...

  5. POJ1077&&HDU1043(八数码,IDA*+曼哈顿距离)

    Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30127   Accepted: 13108   Special ...

  6. luogu_1379 八数码难题

    八数码-->BFS+set #include<iostream> #include<cstdlib> #include<cstdio> #include< ...

  7. HDU-1043 Eight八数码 搜索问题(bfs+hash 打表 IDA* 等)

    题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原 ...

  8. hdu1043 经典的八数码问题 逆向bfs打表 + 逆序数

    题意: 题意就是八数码,给了一个3 * 3 的矩阵,上面有八个数字,有一个位置是空的,每次空的位置可以和他相邻的数字换位置,给你一些起始状态 ,给了一个最终状态,让你输出怎么变换才能达到目的. 思路: ...

  9. poj 1077-Eight(八数码+逆向bfs打表)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

随机推荐

  1. 《Linux内核设计与实现》读书笔记(三)- Linux的进程

    进程是所有操作系统的核心概念,同样在linux上也不例外. 主要内容: 进程和线程 进程的生命周期 进程的创建 进程的终止 1. 进程和线程 进程和线程是程序运行时状态,是动态变化的,进程和线程的管理 ...

  2. MySQL 文件导入出错

    ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot exec ...

  3. enter键触发事件的清除

    使用iframe弹窗时 父级页面 初始化的时候 给enter键绑定了事件 在子页面中 按下enter键会触发 而报错,此时在本页面的初始化的时候 将enter键绑定的方法取消 即可: $(docume ...

  4. 51nod1049(最大子段和2)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1049 题意:中文题诶- 思路:本题和51nod1049(题解 ...

  5. 对各种lca算法的理解

    1.RMQ+ST 首先注意这个算法的要素:结点编号,dfs序,结点深度. 首先dfs,求出dfs序,同时求出每个结点的深度.然后st算法,维护深度最小的结点编号(dfs序也可以,因为他们俩可以互相转换 ...

  6. Jmeter-线程时间

    随手记录下自己在学习遇到的线程时间问题 1.线程数14个,要求每秒进入2个线程,这设置准备时长因为7秒       及准备时长 = 线程数/每秒需要进入的线程数量      如上列中:准备时间 = 1 ...

  7. HDU2050 折线分割平面

    题目:acm.hdu.edu.cn/showproblem.php?pid=2050 递推: 从直线入手,第n条直线,最多和平面上的直线有n-1个交点,多出(n-1)+1个部分 序号 1 2 3 .. ...

  8. 不要忽视Web编程中的小细节

    概述:长时间以来,我们创造了某些在构造和范围内用以提升网站易用性的约定和实践.然后在我们进行web编程的时候总有一些疏忽和纰漏.这里总结了一些web编程时容易出现的小错误,并给出了相应的补救方法,希望 ...

  9. springMvc配置 中文api

    http://7xvpsh.com1.z0.glb.clouddn.com/publish/21-2/the-dispatcher-servlet.html springmvc4.1.7:配置 复制转 ...

  10. URAL 2080 Wallet

    找规律发现只要找到两个相同数字之间,有多少个不同的数字,即为答案. 可以用树状数组离线处理. 坑点是卡有很多张,没用完的情况,后面的卡直接放在哪里, 就是 10 5 1 2 3 4 5 这样 开始数据 ...