Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >八数码问题简单解决办法

八数码问题简单解决办法

作者头像
全栈程序员站长
发布于 2022-09-14 07:33:20
发布于 2022-09-14 07:33:20
38000
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

问题分析:

八数码问题是一个经典的BFS问题,把棋局看成一个状态图,共有9!种状态。从初始棋局开始,每次转移到下个状态,直到目标棋局为止。 仔细分析可知,八数码的关键是判重,如果不去除重复状态,程序会产生很多无效状态,从而复杂度大大增加


解决算法:

BFS + Cantor


案例分析:

(0表示空格所在位置) 初始棋局: |1|2|3| |0|8|4| |7|6|5|

目标棋局: |1|0|3| |8|2|4| |7|6|5|

1.先将空格和8交换得到: |1|2|3| |8|0|4| |7|6|5|

2.再将空格和2交换得到目标棋局: |1|0|3| |8|2|4| |7|6|5|

总共执行两次操作


C++代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <bits/stdc++.h>
using namespace std;

const int LEN = 362880;	// 共9!种状态

struct node
{ 
   
	int state[9];	// 记录八数码排列,即一个状态
	int dis;
};

int dir[4][2] = { 
   	//左,上,右,下顺时针方向
	{ 
   -1,0},
	{ 
   0,-1},
	{ 
   1,0},
	{ 
   0,1},
};

int visited[LEN] = { 
   0};	// cantor判重,若某状态访问过置为一
int start[9];
int goal[9];
long factory[] = { 
   1,1,2,6,24,120,720,5040,40320,362880};	// cantor判重用到的常数,从0!到9!

bool cantor(int str[], int n) { 
   
	long result = 0;
	for(int i=0; i<n; ++i) { 
   
		int cnt = 0;
		for(int j=i+1; j<n; ++j)
			if(str[i] > str[j])
				cnt++;
		result += cnt*factory[n-i-1];
	}
	if(!visited[result]) { 
   
		visited[result] = 1;
		return true;
	}
	else return false;
}

int bfs() { 
   
	node head;
	memcpy(head.state, start, sizeof(head.state));
	head.dis = 0;
	queue<node> q;
	cantor(head.state, 9);
	q.push(head);

	while(!q.empty()) { 
   
		head = q.front();
		q.pop();
		int z;
		for(z=0; z<9; ++z)
			if(head.state[z] == 0)	//寻找元素0的位置
				break;

		// z的二维转换
		int x = z%3;
		int y = z/3;

		// 向四个方向转移新状态
		for(int i=0; i<4; ++i) { 
   
			int nx = x + dir[i][0];
			int ny = y + dir[i][1];
			int nz = ny*3 + nx;	// 二维化一维
			if(nx >= 0 && nx <3 && ny >= 0 && ny < 3) { 
   	//未越界
				node nnode;
				memcpy(&nnode, &head, sizeof(struct node));
				swap(nnode.state[z], nnode.state[nz]);
				nnode.dis++;
				if(memcmp(nnode.state, goal, sizeof(goal)) == 0)	//与目标状态比较
					return nnode.dis;
				if(cantor(nnode.state, 9))	//判重
					q.push(nnode);	//把新的状态放进队列
			}
		}
	}
	return -1;	//没找到
}

int main() { 
   
	//freopen("in.txt", "r", stdin);
	for(int i=0; i<9; ++i)
		cin >> start[i];
	for(int i=0; i<9; ++i)
		cin >> goal[i];
	int num = bfs();
	if(num != -1)
		cout << num << endl;
	else
		cout << "impossible" << endl;
	return 0;
}

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/158112.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年7月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
多种方法求解八数码问题
AI的实验报告,改了改发上来。希望路过的大牛不吝赐教。非常是纳闷我的ida*怎么还没有双搜快。还有发现基于不在位启示的A*和Ida*都挺慢。尤其是ida* 搜索31步的竟然要十几秒。是我写的代码有问题吗?忘路过的大牛指导啊!!!!
全栈程序员站长
2022/07/13
7490
多种方法求解八数码问题
【算法竞赛 - 搜索】Eight II
只是缺少了始末状态一致的数据,导致我血压高了几小时。(和标程对拍没有问题,交上去就WA)
Livinfly
2022/10/26
2150
八数码问题高效算法-HDU 1043
八数码问题是bfs中的经典问题,经常也会遇到与其相似的题目。用到的思想是bfs+hash;主要是由于状态分散,无法直接用一个确定的数表示。所以导致bfs时,无法去判断一个状态是否已经被搜过。也无法用d数组去求解。这个时候就需要用到hash的方法判断当前状态是否已经被搜过。并按照搜索的顺序给每个状态编号(用这个编号代替对应的状态,与状态一一对应,为了求d[]),将所有的状态存起来,供hash查找。
ACM算法日常
2018/08/07
5280
八数码问题高效算法-HDU 1043
【POJ 2251】Dungeon Master(bfs)
题意 3维的地图,求从S到E的最短路径长度 题解 bfs 代码 #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define N 35 using namespace std; struct node{ int x,y,z,d; }s,e; int L,R,C; int m[N][N][N],vis[N][N][N]; int ans; int dx[7]={0,0,0,0,1,-1}; int dy[
饶文津
2020/06/02
3090
A*算法之八数码问题 python解法
人工智能课程中学习了A*算法,在耗费几小时完成了八数码问题和野人传教士问题之后,决定写此文章来记录一下,避免忘记
全栈程序员站长
2022/07/22
3.1K0
A*算法之八数码问题 python解法
LeetCode 286. 墙与门(BFS)
你要给每个空房间位上填上该房间到 最近 门的距离,如果无法到达门,则填 INF 即可。
Michael阿明
2020/07/13
1.2K0
【图论搜索专题】灵活运用多种搜索方式进行求解 Ⅱ(含启发式搜索)
Tag : 「BFS」、「最小步数」、「AStar 算法」、「启发式搜索」在一个 2 x 3 的板上(board)有 块砖瓦,用数字 1~5 来表示, 以及一块空缺用 来表示.一次移动定义为选择 与一个相邻的数字(上下左右)进行交换.最终当板 board 的结果是 谜板被解开。给出一个谜板的初始状态,返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 。
宫水三叶的刷题日记
2021/12/02
4320
蓝桥杯官网 试题 PREV-111 历届真题 大胖子走迷宫【第十届】【决赛】【研究生组】【C++】【Java】【Python】三种解法
为帮助大家能在6月18日的比赛中有一个更好的成绩,我会将蓝桥杯官网上的历届决赛题目的四类语言题解都发出来。希望能对大家的成绩有所帮助。
红目香薰
2022/11/30
2540
蓝桥杯官网 试题 PREV-111 历届真题 大胖子走迷宫【第十届】【决赛】【研究生组】【C++】【Java】【Python】三种解法
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1001 跳马
        这段时间我会把蓝桥杯官网上的所有非VIP题目都发布一遍,让大家方便去搜索,所有题目都会有几种语言的写法,帮助大家提供一个思路,当然,思路只是思路,千万别只看着答案就认为会了啊,这个方法基本上很难让你成长,成长是在思考的过程中找寻到自己的那个解题思路,并且首先肯定要依靠于题海战术来让自己的解题思维进行一定量的训练,如果没有这个量变到质变的过程你会发现对于相对需要思考的题目你解决的速度就会非常慢,这个思维过程甚至没有纸笔的绘制你根本无法在大脑中勾勒出来,所以我们前期学习的时候是学习别人的思路通过自己的方式转换思维变成自己的模式,说着听绕口,但是就是靠量来堆叠思维方式,刷题方案自主定义的话肯定就是从非常简单的开始,稍微对数据结构有一定的理解,暴力、二分法等等,一步步的成长,数据结构很多,一般也就几种啊,线性表、树、图、再就是其它了。顺序表与链表也就是线性表,当然栈,队列还有串都是属于线性表的,这个我就不在这里一一细分了,相对来说都要慢慢来一个个搞定的。蓝桥杯中对于大专来说相对是比较友好的,例如三分枚举、离散化,图,复杂数据结构还有统计都是不考的,我们找简单题刷个一两百,然后再进行中等题目的训练,当我们掌握深度搜索与广度搜索后再往动态规划上靠一靠,慢慢的就会掌握各种规律,有了规律就能大胆的长一些难度比较高的题目了,再次说明,刷题一定要循序渐进,千万别想着直接就能解决难题,那只是对自己进行劝退处理。加油,平常心,一步步前进。
红目香薰
2023/02/23
3410
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1001 跳马
使用C++解决八数码问题
问题描述:通过单步移动把下面的矩阵移动成1-8环绕一周的矩阵(即0在中间,1-8顺序排成一圈,1在哪无所谓)
全栈程序员站长
2022/09/14
6430
【算法竞赛 - 搜索】八数码
题目跳转 POJ1077 Eight 题目大意 经典八数码问题,无需赘述。 本人思路 BFS - 康托展开 - A* 上下左右移动的操作直接自己想好二维的形态,直接在一维中实现 将每个没有在自己位置的棋子与自己的应在的位置的曼哈顿距离之和作为估价函数f 康托展开进行哈希 我的其他思路: 用map代替康托展开来哈希 不加A* TLE 加了A* 比康托展开慢 康托展开的复杂度为O(n^2),而map的时间复杂度为O(nlogn),但是不难发现,用map实现时,会多次调用map中时间复杂度为O(logn)的函数
Livinfly
2022/10/26
3350
八数码问题及A*算法
一.八数码问题 八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。 所谓问题的一个状态就是棋子在棋盘上的一种摆法。棋子移动后,状态就会发生改变。解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。 八数码问题一般使用搜索法来解。 搜索法有广度优先搜索法、深度优先搜索法、A*算法等。这里通过用不同方法解八数码问题来比较一下不同搜索法的效果。
全栈程序员站长
2022/09/07
1.2K0
A*算法解决八数码问题
八数码游戏包括一个33的棋盘,棋盘上摆放着8个数字的棋子,留下一个空位。与空位相邻的棋子可以滑动到空位中。游戏的目的是要达到一个特定的目标状态。标注的形式化如下:
全栈程序员站长
2022/07/23
1.5K0
搜索专题3 | 八数码 HDU - 1043
本搜索专题会参考vjudge上的《kuangbin带你飞》系列题目,前面2篇是基础题,后面会慢慢复杂起来!加油!
ACM算法日常
2019/08/21
5040
搜索专题3 | 八数码 HDU - 1043
​C++ 八数码问题理解 IDA* 算法原则:及时止损,缘尽即散
状态搜索问题指由一种状态转换到到最终状态,求解中间需要经过多少步转换,或者说最小需要转换多少步,或者说有多少种转换方案。本文和大家聊聊八数码问题的IDA*算法解决方案,也是想通过此问题,深入理解IDA*算法的的底层思维逻辑。
一枚大果壳
2024/02/22
2770
​C++ 八数码问题理解 IDA* 算法原则:及时止损,缘尽即散
a算法解决八数码实验报告_人工智能核心算法
熟悉和掌握启发式搜索的定义、估价函数和算法过程,并利用A*算法求解N数码难题,理解求解流程和搜索顺序。
全栈程序员站长
2022/11/17
3.6K0
a算法解决八数码实验报告_人工智能核心算法
问题 1426: [蓝桥杯][历届试题]九宫重排
总的来说题意就是看两个字符串经过最少多少步能成为相同的,我是用广搜做的,有上下左右四个方向,把把两个位置的数字和’.'调换,看和想要的字符串是否相同,用map记录字符串是否出现过,这样只要搜到就一定是最短的。结果很不幸的超时了。最后用了双向BFS,把尾部的字符串也加入队列,同时搜索,用maps标记字符串是否出现过,如果是从初态转化而来,标记为1,如果是从终态转化而来,标记为2,用temp来记录步数,当双方有交替的时候就证明搜索成功。
杨鹏伟
2020/09/11
2850
7种方法求解八数码问题
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
全栈程序员站长
2022/07/22
1.1K0
7种方法求解八数码问题
搜索专题2 | 3D地宫寻路 POJ - 2251
上一篇我们做了一道棋子摆放的题目,采用的是DFS算法,本篇是一篇BFS算法,在刚开始学习搜索算法的时候,会觉得DFS和BFS算法非常相似,因为都是搜索然后得到结果。
ACM算法日常
2019/08/14
5100
搜索专题2 | 3D地宫寻路 POJ - 2251
【ZOJ2278】Fight for Food(dp)
给定一个10*10以内的地图,和p(P<=30000)只老鼠,给定其出现位置和时间T(T<=1,000,000,000),求最多抓到几只老鼠。
饶文津
2020/06/02
2170
【ZOJ2278】Fight for Food(dp)
推荐阅读
相关推荐
多种方法求解八数码问题
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文