八数码问题简单解决办法

八数码问题简单解决办法问题分析:八数码问题是一个经典的BFS问题,把棋局看成一个状态图,共有9!种状态。从初始棋局开始,每次转移到下个状态,直到目标棋局为止。仔细分析可知,八数码的关键是判重,如果不去除重复状态,程序会产生很多无效状态,从而复杂度大大增加解决算法:BFS+Cantor案例分析:(0表示空格所在位置)初始棋局:|1|2|3||0|8|4||7|6|5|目标棋局:|1|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++代码:


#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.net/158112.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 计算机三级-数据库技术

    计算机三级-数据库技术三级数据库技术知识点总结1数据字典是对系统种各类数据描述的集合,包括数据项,数据结构,数据流,数据存储和处理过程五个部分2数据模型的三要素:数据结构、数据操作和完整性约束3数据库系统:一般由数据库、操作系统、数据库管理系统(及其工具)、应用系统、数据库管理人员和用户构成4数据模型:数据模型是数据库系统的数学形式框架,是数据库系统的核心和基础5数据模型的分类:概念模型,也称信息…

    2022年6月18日
    48
  • Android游戏引擎_巨星引擎网络公司

    Android游戏引擎_巨星引擎网络公司学Android游戏开发的朋友,往往会显得有些无所适从,他们常常不知道该从何处入手,每当遇到自己无法解决的难题时,又往往会一边羡慕于iPhone下有诸如Cocos2d-iphone之类的免费游戏引擎可供使用,一边自暴自弃的抱怨Android平台游戏开发难度太高,又连个像样的游戏引擎也没有,甚至误以为使用Java语言开发游戏是一件费力不讨好且没有出路的事情。事实上,这种想法完全是没有必要且不

    2025年11月27日
    2
  • navicat15手动激活码【2021.7最新】

    (navicat15手动激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.htmlMLZPB5EL5Q-eyJsaWNlbnNlSWQi…

    2022年3月21日
    533
  • md5 java 实现_MD5加密的Java实现

    md5 java 实现_MD5加密的Java实现在各种应用系统中,如果需要设置账户,那么就会涉及到储存用户账户信息的问题,为了保证所储存账户信息的安全,通常会采用MD5加密的方式来,进行储存。首先,简单得介绍一下,什么是MD5加密。MD5的全称是Message-DigestAlgorithm5(信息-摘要算法),在90年代初由MITLaboratoryforComputerScience和RSADataSecurityInc的…

    2022年7月9日
    18
  • 从简单的信道预计说起

    从简单的信道预计说起

    2021年11月15日
    40
  • W3C标准详解_关于w3c标准下列说法错误的是

    W3C标准详解_关于w3c标准下列说法错误的是W3C标准详解w3c(即万维网联盟WorldWideWebConsortium)标准不是一个标准,而是一系列标准的集合。网页主要有三部分组成结构(Structrue),表现(Presentation),行为(Behavior)。W3c简介:W3c即万维网联盟,创建于1994年,是Web技术领域最权威和影响力的国际中立性技术标准机构。到目前为止,W3C已经发布了200多项影响深远的w…

    2025年12月15日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号