八数码简介

八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每一个棋子上标有1至8的某一数字,不同棋子上标的数字不同样。棋盘上另一个空格,与空格相邻的棋子能够移到空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。所谓问题的一个状态就是棋子在棋盘上的一种摆法。棋子移动后,状态就会发生改变。解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。

求解八数码问题要懂得的知识

1.康托展开,八数码在交换的过程中状态会改变,康托展开用于求出某一格局的状态数。唐托展开公式:X=a[n](n-1)!+a[n-1](n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!其中a[i]为当前未出现的元素中是排在第几个(从0开始),并且0<=a[i]

2.逆序数,通过求初始格局和目标格局逆序数,然后在比较两者的逆序数的奇偶性是否相同,如果奇偶性相同,则可以从初始格局变到目标格局。否则,不可达。逆序数求法:假设有n个元素的排列,a[i]为排列中的元素(0<=i

3.在八数码中0位置的数与它相邻的上下左右的位置的数交换不会影响这个格局的逆序数的奇偶性。比如有以下格局:

4

6

7

5

8

1

2

3

0

如果2这个数和5这个数交换就会导致格局的逆序数的奇偶性的变化,而如果0和1交换就不会导致奇偶性的变化。我们要保证移动前和移动后逆序数的奇偶性不改变,用一维数组来存储格局,要注意索引。

广度优先搜索求解八数码问题代码

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define N 9

int jc[N+1]={1,1,2,6,24,120,720,5040,40320,362880};//0-9的阶乘

typedef struct data

{

int arr[N];//格局

int hash;//存储某一格局的哈希

int pos;//0当前位置

int step;//记录步数

}Node;

int dir[4][2]={

{0,1},

{1,0},

{0,-1},

{-1,0}

};

/**

* 康托展开

*/

int cantor(int arr[N])

{

int i,j;

int sum=0;

for( i=0;i

{

int nmin=0;

for(j=i+1;j

{

if(arr[i]>arr[j])

nmin++;

}

sum+=(nmin*jc[N-i-1]);

}

return sum;

}

/**

*数据交换

*/

void swap(int *arr,int i,int j)

{

int t=arr[i];

arr[i]=arr[j];

arr[j]=t;

}

/**

* 打印数组,测试用

*/

void printArray(int * arr)

{

int i,j;

for (i=0;i

{

if(i%3==0)

cout<

cout<

}

cout<

}

/**

* 复制数组

*/

void copyArray(int src[N],int target[N])

{

int i;

for(i=0;i

{

target[i]=src[i];

}

}

/**

* 广搜

*/

int bfs(int arr[N],int sHash,int tHash)

{

if(sHash==tHash)

return 0;

int i,j;

queue q;

set setHash;

Node now,next;

copyArray(arr,now.arr);

int pos=0;

for (i=0;i

{

if(arr[i]==0)

break;

pos++;

}

now.hash=sHash;

now.step=0;

next.step=0;

now.pos=pos;

q.push(now);

setHash.insert(now.hash);

while(!q.empty())

{

now=q.front();

q.pop();

for (i=0;i<4;i++)

{

int offsetX=0,offsetY=0;

offsetX=(now.pos%3+dir[i][0]);

offsetY=(now.pos/3+dir[i][1]);

if(offsetX>=0&&offsetX<3&&offsetY<3&&offsetY>=0)

{

copyArray(now.arr,next.arr);//每次换方向,就复制

next.step=now.step;

next.step++;

swap(next.arr,now.pos,offsetY*3+offsetX);

next.hash=cantor(next.arr);

next.pos=(offsetY*3+offsetX);

int begin=setHash.size();

setHash.insert(next.hash);

int end=setHash.size();

if(next.hash==tHash){

return next.step;

}

if(end>begin)

{

q.push(next);

}

}

}

}

return -1;

}

/**

*求逆序数

*/

int inversion(int arr[N])

{

int sum=0;

for(int i=0;i

{

for(int j=i+1;j

{

if(arr[j]

{

sum++;

}

}

}

return sum;

}

int main(int argc, char **argv)

{

int i,j;

string s="123456780";

string t="123456078";

int is[N],it[N];//源int数组和目标int数组

for (i=0;i<9;i++)

{

if (s.at(i)>='0'&&s.at(i)<='8')

{

is[i]=s.at(i)-'0';

}else

{

is[i]=0;

}

if (t.at(i)>='0'&&t.at(i)<='8')

{

it[i]=t.at(i)-'0';

}else

{

it[i]=0;

}

}

int sHash,tHash;//源哈希和目标哈希

sHash=cantor(is);

tHash=cantor(it);

int inver1=inversion(is);//求初始格局的逆序数

int inver2=inversion(it);//求目标格局的逆序数

if((inver1+inver2)%2==0)

{

int step=bfs(is,sHash,tHash);

cout<

}

else

{

cout<

}

return 0;

}

java宽度优先搜索之八数码,广度优先搜索解决八数码问题相关推荐

  1. 题目2:隐式图的搜索问题(A*算法解决八数码)

    数据结构课程实践系列 题目1:学生成绩档案管理系统(实验准备) 题目2:隐式图的搜索问题(A*算法解决八数码) 题目3:文本文件单词的检索与计数(实验准备) 文章目录 数据结构课程实践系列 题目1:学 ...

  2. 题目2:隐式图的搜索问题(A*算法解决八数码)代码实现

    从起点 开始,把它加入到一个由方格组成的open list(开放列表) 中,这个open list像是一个购物清单.Open list里的格子是可能会是沿途经过的,也有可能不经过.因此可以将其看成一个 ...

  3. 宽度优先搜索算法解决八数码问题

    宽度优先搜索算法解决八数码问题 原理 1.宽度优先搜索是指在一个搜索树中,搜索以同层邻近节点依次扩展节点.这种搜索是逐层进行的,在对下一层的任一节点进行搜索之前,必须搜索完本层的所有节点. 宽度优先搜 ...

  4. 搜索技术【广度优先搜索】 - 嵌套广度优先搜索 【POJ No. 1475】 推箱子 Pushing Boxes

    搜索技术[广度优先搜索] - 嵌套广度优先搜索 [POJ No. 1475] 推箱子 Pushing Boxes 在广度优先搜索里面嵌套广度优先搜索的算法被称为嵌套广度优先搜索(或称双重广度优先搜索) ...

  5. 深度优先搜索遍历与广度优先搜索遍历

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 深度优先 ...

  6. 数据结构--图--图的数组存储表示,深度优先搜索遍历和广度优先搜索遍历

    图有四种存储结构:数组,邻接表,十字链表,邻接多重表.下面以数组为存储结构来实现图的深度优先搜索遍历和广度优先搜索遍历.其中广度优先搜索遍历中有用到STL中的queue,注意头文件的包含.具体代码如下 ...

  7. 深度优先搜索解决八数码难题

    八数码问题 以前用java写的通过深度优先瘦素解决八数码难题. 对于八数码难题来说,可以把9宫格看成一个[3][3]的二维数组,将空格位置看成0,将0可以移动的方向看成树的枝丫,分为上下左右4个方向. ...

  8. 广度优先算法解决8数码问题【c++】

    8数码问题 (广度优先算法解决----c++) 8数码问题问题描述 八数码问题也称为九宫问题,在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格(空格用0来表示),空格 ...

  9. A*算法解决八数码问题 Java语言实现

    A*算法解决八数码问题 Java语言实现 参考文章: (1)A*算法解决八数码问题 Java语言实现 (2)https://www.cnblogs.com/beilin/p/5981483.html ...

  10. Python利用A*算法解决八数码问题

    资源下载地址:https://download.csdn.net/download/sheziqiong/86790565 资源下载地址:https://download.csdn.net/downl ...

最新文章

  1. IE与Firefox的CSS兼容
  2. matlab神经网络函数
  3. 用 TigerVNC 实现 Linux 远程桌面
  4. 汇编学习(五)——表处理程序
  5. C++通过WMI获取硬件配置信息
  6. Ubuntu各个版本国内源
  7. 不能说服别人接受,只能是个烂设计
  8. 华为NP课程笔记27-QINQ概述
  9. access查询top10产品_access数据库 top
  10. java技术经理面试题
  11. Scrum大白话总结
  12. 【转载】linux top命令及参数详解
  13. @Primary 和 @Qualifier的区别
  14. 带时滞的病毒模型计算模板【基于matlab的动力学模型学习笔记_1】
  15. 用instsrv.exe+srvany.exe将应用程序安装为windows服务
  16. STP——MSTP理论讲解
  17. 【论文翻译】【剪枝】Filter Pruning via Geometric Medianfor Deep Convolutional Neural Networks Acceleration
  18. PMP项目管理项目资源管理
  19. 2021年学vue还是react好
  20. Unity接入海康网络摄像头SDK

热门文章

  1. 并联串联混合的电压和电流_初中物理归纳并联和串联的区别
  2. 16.第二十二章.信息安全管理
  3. 全球数据共享网站集合
  4. 前端练习-CSS布局
  5. 阮兄弟的致远OAa8v5移动端增加功能和OEM实例
  6. 云联惠认证身份_在秘乐短视频上实名认证了,输入了手机号,身份证号码,姓名,人脸识别,会被网贷吗?...
  7. 《仿人机器人原理与实战》一第1章
  8. dwg格式的计算机图,例举电脑dwg文件怎么打开
  9. 3dmax2014 uv用法_3dmax中UV贴图的使用方法
  10. matlab——取整函数