Eight

Descriptions:

简单介绍一下八数码问题:
在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图:

1 2 3
4 5 6
7 8  

在上图中,由于右下角位置是空的,你可以移动数字,比如可以将数字6下移一位:

1 2 3   1 2 3
4 5 6 4 5  
7 8     7 8 6

或者将数字8右移一位:

1 2 3   1 2 3
4 5 6 4 5 6
7 8     7   8

1~8按顺序排列的情况称为“初始状态”(如最上方图)。“八数码问题”即是求解对于任意的布局,将其移动至“初始状态”的方法。 
给定一个现有的九宫格布局,请输出将它移动至初始状态的移动方法的步骤。
Input

输入包含多组数据,处理至文件结束。每组数据占一行,包含8个数字和表示空位的‘x’,各项以空格分隔,表示给定的九宫格布局。 
例如,对于九宫格

1 2 3
  4 6
7 5 8

输入应为:1 2 3 x 4 6 7 5 8

Output

对于每组输入数据,输出一行,即移动的步骤。向上、下、左、右移动分别用字母u、d、l、r表示;如果给定的布局无法移动至“初始 状态”,请输出unsolvable。
如果有效的移动步骤有多种,输出任意即可。

Sample Input

2  3  4  1  5  x  7  6  8

Sample Output

ullddrurdllurdruldr

题目链接

https://vjudge.net/problem/HDU-1043

其实就是反向bfs,不过用了一个新的方法去存放拼图序列,康托展开即把拼图(x12345678)全排列,再用数字去表示,简而言之就是用不同的数字去代替拼图序列,使之跟简单、快速的搜索

不会康托展开不关系,点击下面链接,现学现会

https://www.cnblogs.com/sky-stars/p/11216035.html

AC代码

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define Mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x,y) memset(x,y,sizeof(x))
#define Maxn 362880+5//876543210的hash值为362880 即最多出现362880种可能
using namespace std;
static const int FAC[] = {, , , , , , , , , }; // 阶乘
struct node
{
string path;//路径
int hashs;//hash值
int pos;//0的位置
};
node now,net;
queue<node>q;
int dt[][]= {{,},{-,},{,},{,-}};//四个方向
char op[]="udlr";//这个与上面的搜索方向是反的,因为是反向bfs
int tmp[];//临时存储拼图的序列
int result=;//123456780 最终答案的hash值
string path[Maxn];//path[x] hash值为x的路径
int vis[Maxn];//vis[x] hash值为x的拼图序列是否标记过
//康托展开
int cantor(int *a)
{
int x = ;
for (int i = ; i < ; ++i)
{
int smaller = ; // 在当前位之后小于其的个数
for (int j = i + ; j < ; ++j)
{
if (a[j] < a[i])
smaller++;
}
x += FAC[ - i - ] * smaller; // 康托展开累加
}
return x+; // 康托展开值
}
//逆康托展开
void decantor(int x, int *a)
{
vector<int> v; // 存放当前可选数
for(int i=; i<; i++)
v.push_back(i);
for(int i=; i<; i++)
{
int r = x % FAC[-i-];
int t = x / FAC[-i-];
x = r;
sort(v.begin(),v.end());// 从小到大排序
a[i]=v[t]; // 剩余数里第t+1个数为当前位
v.erase(v.begin()+t); // 移除选做当前位的数
}
}
void bfs()
{
MEM(vis,);//初始化
for(int i=; i<; i++)//tmp一开始为123456780,从这开始打散拼图
tmp[i]=i+;
tmp[]=;
now.pos=;
now.hashs=result;
now.path="";
path[result]="";
vis[result]=;
q.push(now);
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=; i<; i++)//四个方向
{
int tx=now.pos/+dt[i][];
int ty=now.pos%+dt[i][];
if(tx>=&&ty>=&&tx<=&&ty<=)//没走出去拼图
{
net=now;
net.pos=tx*+ty;
decantor(now.hashs-,tmp);//求tmp
swap(tmp[now.pos],tmp[net.pos]);//得到新的tmp
net.hashs=cantor(tmp);//得到新tmp对应的hash
if(!vis[net.hashs])//这都bfs老套路了 没啥说的
{
vis[net.hashs]=;
net.path=op[i]+net.path;
q.push(net);
path[net.hashs]=net.path;
}
}
}
}
return;
}
int main()
{
bfs();
char x;
while(cin>>x)//输入格式 没啥说的
{
if(x=='x')
{
now.pos=;
tmp[]=;
}
else
{
tmp[]=x-'';
}
for(int i=; i<; i++)
{
cin>>x;
if(x=='x')
{
now.pos=i;
tmp[i]=;
}
else
{
tmp[i]=x-'';
}
}
now.hashs=cantor(tmp);//求出tmp这个拼图序列的hash值
if(!vis[now.hashs])//这个hash没标记过,即没产生过这个拼图序列
cout<<"unsolvable"<<endl;
else
cout<<path[now.hashs]<<endl;//输出hash的路径
}
return ;
}

【HDU - 1043】Eight(反向bfs+康托展开)的更多相关文章

  1. HDU 1043 Eight(反向BFS+打表+康托展开)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...

  2. hdu.1430.魔板(bfs + 康托展开)

    魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  3. HDU 1043 Eight (A* + HASH + 康托展开)

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  4. HDU_1043 Eight 【逆向BFS + 康托展开 】【A* + 康托展开 】

    一.题目 http://acm.hdu.edu.cn/showproblem.php?pid=1043 二.两种方法 该题很明显,是一个八数码的问题,就是9宫格,里面有一个空格,外加1~8的数字,任意 ...

  5. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  6. POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3

    http://poj.org/problem?id=1077 http://acm.hdu.edu.cn/showproblem.php?pid=1043 X=a[n]*(n-1)!+a[n-1]*( ...

  7. HDU 1430 魔板(康托展开+BFS+预处理)

    魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  8. HDU - 1430 魔板 【BFS + 康托展开 + 哈希】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1430 思路 我刚开始 想到的 就是 康托展开 但是这个题目是 多组输入 即使用 康托展开 也是会T的 ...

  9. hdu 1430 (BFS 康托展开 或 map )

    第一眼看到这题就直接BFS爆搜,第一发爆了内存,傻逼了忘标记了,然后就改,咋标记呢. 然后想到用map函数,就8!个不同的排列,换成字符串用map标记.然后又交一发果断超时,伤心,最恨超时,还不如来个 ...

随机推荐

  1. vs编译在win xp电脑上运行的win32程序遇到的问题记录(无法定位程序输入点GetTickCount64于动态链接库KERNEL32.dll)

    直接编译后运行,弹出提示框:不是有效的win32应用程序 像之前那样把msvcr110.dll复制过去依然报错: 这是因为vs2012编译的win32程序用到的系统函数在xp环境上对应不上.之前转载的 ...

  2. [java代码库]-简易计算器(第一种)

    简易计算器(效果如图所示) 第一种方案:采用Javascript+html完成计算器,支持+-*/,结果显示不允许使用input输入域(可以考虑使用<span>) <html> ...

  3. 原生Js汉语拼音首字母匹配城市名/自动提示列表

    根据城市的汉语名称首字母把城市排序,基本思路: 1.处理数据,按照需要的格式分别添加{HOT:{hot:[],ABCDEFG:{a:[1,2,3],b:[1,2,3]},HIGHLMN:{},OPQR ...

  4. 【Linux】Linux 环境下splite以及一些正则使用

    由于在windows下,遍历目录,想查找满足条件的文件: dir /s > ..\fileresult.txt 结果得到的文件过大,999多MB的txt: split -b 10k date.f ...

  5. MongoDB自学日记3——架构及HA

    在对mongoDB的操作有了一定基础后,终于可以扯扯HA和架构这两个高大上的概念了.在这之前当然还得弄清楚mongoDB的Key feature:Sharding. 1. Sharding Shard ...

  6. jQuery中的Ajax应用<思维导图>

    传统的WEB应用程序模型是这样工作的:当用户的界面操作触发HTTP请求,服务器在接到请求后进行一些业务逻辑处理,如保存数据等,然后向客户端返回一个html页面.但这种方式并没有给予用户很好的应用体验, ...

  7. localstorage实现带过期时间的缓存功能

    前言 一般可以使用cookie,localstorage,sessionStorage来实现浏览器端的数据缓存,减少对服务器的请求. 1.cookie数据存放在本地硬盘中,只要在过期时间之前,都是有效 ...

  8. [代码修订版] Python 踩坑之旅进程篇其五打不开的文件

    目录 1.1 踩坑案例 1.2 填坑和分析 1.2.1 从程序优化入手 1.2.2 从资源软硬限入手 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: ...

  9. zphp源码分析(一)

    zphp是一款轻量级的php服务端框架,是swoole官方开发的.可以用来开发web应用和网络服务. 安装: 可以通过composer安装, { "require": { &quo ...

  10. php抽奖概率程序

    抽奖概率思想: 1.给每一个奖项设置要给概率数,如下面所有奖品综合设置为100,iphone5s是5,也就是5% 2.然后通过php生成随机数函数生成一个在总概率之间的随机数 如:抽第一个奖品5s的时 ...