HDU 1043八数码问题

  八数码,就是1~8加上一个空格的九宫格,这道题以及这个游戏的目标就是把九宫格还原到从左到右从上到下是1~8然后最后是空格。

  没了解康托展开之前,这道题怎么想都觉得很棘手,直接搜索的话也不知道怎么剪枝,而且判重也不可能开一个9维的数组,空间也不允许,所以先了解康托展开是无可厚非的第一步,这里就引用一下大佬的介绍,很简单很实用的关于全排列的一个东西

  康托展开和逆康托展开

  学会康托展开之后这道题就有很多解法了,很多是用A*的,不过这个我还没学会,只能弱弱的用万能的搜索来暴力过一切了,当然搜索的做法也有几个,直接暴力的正向搜索单组测试数据是可以的,单多组测试数据的话还是会超时,还有种双向bfs的做法,也就是把当前的数列和我们要的目标数列同时加入队列,然后两个相遇时就可以了。

  不过我个人觉得那两个写起来比较麻烦不好处理,所以我还是采用一个逆向的bfs来打表,为什么可以打表的,了解康托展开后我们可以知道,这题的全排列最多也就9!,那我们完全可以预处理一下,由目标状态去跑到其他状态,把每个状态的康托展开的值作为它的一个编号,由此打表,具体的如代码

 #include<cstdio>
#include<queue>
using namespace std;
const int dir[][]={{,},{,},{,-},{-,}};
const char leg[]={'l','u','r','d'};//因为是逆回去的,所以方向是反的
char s[];
int jc[]={},sm[];
struct Way{
char ans;
int f;
Way(){
f=-;
}
}w[];
struct Node{
int num[];
int kt,p;//康托值,x的位置
};
int kangtuo(int *a)//康托展开
{
int ans=;
for(int i=;i<;i++)
{
int k=;
for(int j=i+;j<;j++)
if(a[i]>a[j])
k++;
ans+=k*jc[-i];
}
return ans;
}
void bfs()
{
queue<Node> q;
Node b;
for(int i=;i<;i++)
b.num[i]=i;
b.kt=,b.p=;
q.push(b);
while(!q.empty())
{
Node e=q.front();
q.pop();
for(int i=;i<;i++)
{
int dx=e.p/+dir[i][];//二维比价好处理位置变化
int dy=e.p%+dir[i][];
if(dx>=&&dx<&&dy>=&&dy<)
{
b=e;b.p=dx*+dy;
int t=b.num[e.p];b.num[e.p]=b.num[b.p];b.num[b.p]=t;
b.kt=kangtuo(b.num);
if(w[b.kt].f==-)
{
w[b.kt].f=e.kt;
w[b.kt].ans=leg[i];
q.push(b);
}
}
}
}
}
int main()
{
for(int i=;i<=;i++)
jc[i]=jc[i-]*i;
bfs();
while(~scanf("%s",s))
{
for(int i=;i<;i++)
scanf("%s",s+i);
for(int i=;i<;i++)
if(s[i]>=''&&s[i]<='')
sm[i]=s[i]-'';
else
sm[i]=;
int kt=kangtuo(sm);
if(w[kt].f==-)//没遍历到这个状态
printf("unsolvable\n");
else
{
while(kt)//回溯输出答案
{
printf("%c",w[kt].ans);
kt=w[kt].f;
}
printf("\n");
}
}
return ;
}

代码千万条,自觉第一条,复制粘贴爽,打铁泪两行

  既然涉及到八数码,最后再补充一个结论,怎么直接判断八数码有没有解,这涉及到逆序数,目标状态1~8的逆序数是0,而上下左右的变换并不会改变逆序数的奇偶性,(这里说的逆序数是不计x的)

所以结论就是,序列的奇偶性要和目标状态一致。

逆向bfs搜索打表+康拓判重的更多相关文章

  1. 八数码问题+路径寻找问题+bfs(隐式图的判重操作)

    Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 p ...

  2. hdu 5012 bfs --- 慎用STL 比方MAP判重

    http://acm.hdu.edu.cn/showproblem.php?pid=5012 发现一个问题 假设Sting s = '1'+'2'+'3'; s!="123"!!! ...

  3. poj3635 FULL tank(TLE) 有限制的最短路(BFS搜索)。

    用的BFS+优先队列+二进制压缩状态判重+链式前向星, TLE,好像有人这样过了...好像要用A*算法,还不太会,所以暂时放弃.但是也学会了很多,学习了链式前向星,更深理解了BFS求最优的时候,什么时 ...

  4. BFS(四):搜索状态判重

    在采用广度优先算法进行搜索时,一个需要重点注意的是在搜索过程中判重和去重.前面介绍的几个例子中,判重都较简单,如采用vis[]数组,若vis[i]==0,则i未访问过,i入队列:若vis[i]!=0, ...

  5. UVA 10651 Pebble Solitaire(bfs + 哈希判重(记忆化搜索?))

    Problem A Pebble Solitaire Input: standard input Output: standard output Time Limit: 1 second Pebble ...

  6. BFS以及hash表判重的应用~

    主要还是讲下hash判重的问题吧 这道题目用的是除法求余散列方式 前几天看了下算法导论 由于我们用的是线性再寻址的方式来解决冲突问题 所以hash表的大小(余数的范围)要包含我们要求的范围 对mod的 ...

  7. 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 ...

  8. hdu 4444 Walk (离散化+建图+bfs+三维判重 好题)

    Walk Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submi ...

  9. HDU1043 Eight(八数码:逆向BFS打表+康托展开)题解

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

随机推荐

  1. 机器猫css

    <html> <head>  <title>机器猫</title>  <style>   div{    width: 30px;    h ...

  2. Python补充4——替换与修改

    最近在自学Python ,在学习过程中发现一个问题,就是Python 的替换与修改. 按照中文思维,替换与修改有什么区别吗?如果发生了部分替换不就是修改了吗?如果修改了不就是新对象替换了老对象吗? 实 ...

  3. python — 生成器、推导式、递归

    目录 1 生成器(函数的变异) 2 推导式 3 递归 1 生成器(函数的变异) 判断一个函数是否是生成器函数:只需看函数内部是否有yield # 生成器函数(内部是否包含yield) def func ...

  4. 【第一季】CH08_FPGA_Button 按钮去抖动实验

    [第一季]CH08_FPGA_Button 按钮去抖动实验 按键的消抖,是指按键在闭合或松开的瞬间伴随着一连串的抖动,这样的抖动将直接影响设计系统的稳定性,降低响应灵敏度.因此,必须对抖动进行处理,即 ...

  5. Go语言GOPATH详解(Go语言工作目录)

    GOPATH 是 Go语言中使用的一个环境变量,它使用绝对路径提供项目的工作目录. 工作目录是一个工程开发的相对参考目录,好比当你要在公司编写一套服务器代码,你的工位所包含的桌面.计算机及椅子就是你的 ...

  6. Java内存管理-探索Java中字符串String(十二)

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 一.初识String类 首先JDK API的介绍: public final class String extends O ...

  7. VBA学习资料分享-1

    近年来,人工智能的概念深入人心,许多企业也正逐步或已推行办公自动化,寻求人力时间成本的降低,从而提升效益.对企业来说,要完全使用人工智能将工作流程自动化恐怕是没那么容易的,可以的话成本也不低,所以使用 ...

  8. 【shell脚本】字符串和数组的使用

    字符串 可以使用单引号和双引号定义字符串变量但是单引号中不支持变量解析 #! /bin/bashusername="mayuan" str_1="hello ${user ...

  9. 80C51串行口

    串行通信是指 使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度 单工.半双工.全双工 单工数据传输只支持数据在一个方向上传输 半双工数据传输允许数据在两个方向上传输,但是,在 ...

  10. Spring7大模块

    Spring 框架是一个分层架构,由 7 个定义良好的模块组成.Spring 模块构建在核心容器之上,核心容器定义了创建.配置和管理 bean 的方式,组成 Spring 框架的每个模块(或组件)都可 ...