BFS-八数码问题与状态图搜索
在一个3*3的棋盘上放置编号为1~8的八个方块,每个占一格,另外还有一个空格。与空格相邻的数字方块可以移动到空格里。任务1:指定的初始棋局和目标棋局,计算出最少的移动步数;任务2:数出数码的移动序列。
把空格看成0,一共有九个数字。
输入样例:
1 2 3 0 8 4 7 6 5
1 0 3 8 2 3 7 6 5
输出样例:
2
1.把一个棋局看成一个状态图,总共有9!= 362880个状态。从初始棋局开始,每次移动转到下一个状态,达到目标棋局后停止。
2.康托展开
康托展开是一种特殊的哈希函数。其功能是在输入一个排列,计算出它在在全排列中从小到大排序的位次。
eg:判断 2143是{1,2,3,4}的全排列中的位次。
(1)首位小于2的所有排列。比2小的只有1,后面三个数的排列有3*2*1=3!个,写成1*3!=6
(2)首位为2,第二位小于1的所有排列。无,写成0*2!=0
(3)前两位为21,第三位小于4的所有排列。只有3一个数,写成1*1!=1
(3)前三位为214,第四位小于3的所有排列。无,写成0*0!=0
求和:1*3!+0*2!+1*1!+0*0!=7
所以位次的计算公式为X = a[n]*(n-1)! +a[n-1]*(n-2)! + … + a[1]*0!
#include<bits/stdc++.h>
#include<queue>
using namespace std; const int len = ; //状态共9! = 362880种
int visited[len] = {};//标记已有状态用来去重
int start[];//起始状态
int goal[];//目标状态
int factory[] = {, , , , , , , , , };//0到9的阶乘
int dir[][] = {{-, }, {, -}, {, }, {, }}; struct node{
int state[];//棋局状态按一维存放下来
int dis;//记录从起始状态移动到当前状态的步数
}; bool cantor(int str[], int n){
int result = ;
for(int i=; i<n; i++){
int cnt = ;
for(int j=i+; j<n; j++){
if(str[i] > str[j])
cnt ++;
}
result += cnt*factory[n-i-];
}
if(!visited[result]){
visited[result] = ;
return ;
}
return ;
} int BFS(){
node head, next;
memcpy(head.state, start, sizeof(head.state));//复制起始状态并插入队列
head.dis = ;
cantor(head.state, );
queue<node>q;
q.push(head); while(!q.empty()){
head = q.front();
q.pop();
int z;
for(z=; z<; z++)
if(head.state[z] == )//找到0
break;
int x = z % ;//将0的一维位置转化为二维的横纵坐标
int y = z / ;
for(int i=; i<; i++){
int newx = x + dir[i][];
int newy = y + dir[i][];
int newz = newx + *newy;//将0移动后重新转化为一维坐标
if(newx>= && newx< && newy>= && newy<){//避免越界
memcpy(&next, &head, sizeof(struct node));
swap(next.state[z], next.state[newz]);//复制原先状态后,改变0的位置
next.dis ++;
if(memcmp(next.state, goal, sizeof(next.state)) == )
return next.dis;
if(cantor(next.state, ))//查重
q.push(next);
}
}
}
return -;
} int main(){
for(int i=; i<; i++)
scanf("%d", start+i);
for(int i=; i<; i++)
scanf("%d", goal+i); int num = BFS();
if(num != -)
printf("%d\n",num);
else
printf("Impossible\n");
}
(1)用于存放状态图的以及步数的结构体
(2)用于移动的数组
(3)用于去重的标记数组
(4)提前算好阶乘存放于数组中
(5)康拓函数判重
(6)BFS函数:queue<node>q;node head, next;
(7)状态图中某数字方块的一维坐标和二维坐标的相互转化
(8)检查坐标是否合法
八数码问题多种解法:https://www.cnblogs.com/zufezzt/p/5659276.html
BFS-八数码问题与状态图搜索的更多相关文章
- BFS(八数码) POJ 1077 || HDOJ 1043 Eight
题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...
- HDU 1043 Eight 八数码问题 A*算法(经典问题)
HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...
- UVALive 6665 Dragonâs Cruller --BFS,类八数码问题
题意大概就是八数码问题,只不过把空格的移动方式改变了:空格能够向前或向后移动一格或三格(循环的). 分析:其实跟八数码问题差不多,用康托展开记录状态,bfs即可. 代码: #include <i ...
- [cdoj1380] Xiper的奇妙历险(3) (八数码问题 bfs + 预处理)
快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚 ...
- 八数码问题+路径寻找问题+bfs(隐式图的判重操作)
Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 p ...
- HDU 1043 Eight (BFS·八数码·康托展开)
题意 输出八数码问题从给定状态到12345678x的路径 用康托展开将排列相应为整数 即这个排列在全部排列中的字典序 然后就是基础的BFS了 #include <bits/stdc++.h ...
- 【算法】BFS+哈希解决八数码问题
15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖“X”; 拼图的目的是安排 ...
- hdu-1043(八数码+bfs打表+康托展开)
参考文章:https://www.cnblogs.com/Inkblots/p/4846948.html 康托展开:https://blog.csdn.net/wbin233/article/deta ...
- 关于八数码问题中的状态判重的三种解决方法(编码、hash、<set>)
八数码问题搜索有非常多高效方法:如A*算法.双向广搜等 但在搜索过程中都会遇到同一个问题.那就是判重操作(假设反复就剪枝),怎样高效的判重是8数码问题中效率的关键 以下关于几种判重方法进行比較:编码. ...
随机推荐
- 使用PropTypes进行类型检查
原文地址 1.组件特殊属性——propTypes 对Component设置propTypes属性,可以为Component的props属性进行类型检查. import PropTypes from ' ...
- SpringBoot缓存 --(一)EhCache2.X
简介: Spring 3.1中开始对缓存提供支持,核心思路是对方法的缓存,当开发者调用一个方法时,将方法的参数和返回值作为key/value缓存起来,当再次调用该方法时,如果缓存中有数据,就直接从缓存 ...
- Umi 小白纪实(三)—— 震惊!路由竟然如此强大!
在<Umi 小白纪实(一)>中有提到过简单的路由配置和使用,但这只是冰山一角 借用一句广告词,Umi 路由的能量,超乎你的想象 一.基本用法 Umi 的路由根结点是全局 layout s ...
- 如何获取 iOS APP 的 scheme URL ?
获取IPA文件 拷贝到桌面上 后缀名由 .ipa 改为 .zip 解压之后进入,进入名为Payload的目录 右键点击里面的跟App同名的文件,选择'显示包内容' 用文本编辑器打开当前文件夹下的inf ...
- 《手把手教你构建自己的 Linux 系统》学习笔记(5)
交叉编译是什么? 交叉编译就是在一个系统上,编译生成另外一个系统运行的程序文件. 「硬件体系结构」和「操作系统」的关系是什么? 硬件体系结构也可以称为架构,主要是通过 CPU 的指令集来进行区分的,操 ...
- EasyUI笔记(四)菜单和按钮
本系列只列出一些常用的属性.事件或方法,具体完整知识请查看API文档 Menu(菜单) 菜单组件通常用于快捷菜单.他是构建其他菜单组件的必备基础组件.比如:menubutton和splitbutton ...
- centos7查看启动的进程并杀死
https://www.cnblogs.com/aipiaoborensheng/p/7676364.html ps -a -H kill -9 pid
- Android布局样式
本篇介绍一下Android中的几种常用的布局,主要介绍内容有: ·View视图 ·LinearLayout ·RelativeLayout 在介绍布局之前,我们首先要了解视图View的基本属性,因为所 ...
- Hadoop学习之路(9)ZooKeeper安装
文章目录 1.环境准备 1.1下载zooKeeper 1.3安装zooKeeper 1.4配置zooKeeper环境变量 1.5 修改zookeeper集群配置文件 1.6 创建myid文件 1.7 ...
- Codeforces Round #620 (Div. 2) D
构造一个排列,要求相邻之间的数满足给定的大小关系,然后构造出两个序列,一个序列是所有可能的序列中LIS最长的,一个所有可能的序列中LIS最短的 最短的构造方法:我们考虑所有单调递增的部分,可以发现要让 ...