题解-八数码问题

八数码问题

描述

八方块移动游戏要求从一个含 8 个数字(用 1-8 表示)的方块以及一个空格方块(用 0 表示)的 3 × 3 矩阵的起始状态开始,不断移动该空格方块以使其和相邻的方块互换,直至达到所定义的目标状态。空格方块在中间位置时有上、下、左、右 4 个方向可移动,在四个角落上有 2个方向可移动,在其他位置上有 3 个方向可移动。例如,假设一个 3× 3 矩阵的初始状态为:

8 0 3
2 1 4
7 6 5
目标状态为:
1 2 3
8 0 4
7 6 5

则一个合法的移动路径为:

8 0 3 > 8 1 3 > 8 1 3 > 0 1 3 > 1 0 3 > 1 2 3
2 1 4 > 2 0 4 > 0 2 4 > 8 2 4 > 8 2 4 > 8 0 4
7 6 5 > 7 6 5 > 7 6 5 > 7 6 5 > 7 6 5 > 7 6 5

另外,在所有可能的从初始状态到目标状态的移动路径中,步数最少的路径被称为最短路径;在上面的例子中,最短路径为 5 。如果不存在从初试状态到目标状态的任何路径,则称该组状态无解。 请设计有效的(细节请见评分规则)算法找到从八方块的某初试状态到某目标状态的所有可能路径中的最短路径。

输入

程序需读入初始状态和目标状态,这两个状态都由 9 个数字组成( 0 表示空格, 1-8 表示 8个数字方块),每行 3 个数字,数字之间用空格隔开。

输出

如果输入数据有解,输出一个表示最短路径的非负的整数;如果输入数据无解,输出 -1 。

输入样例 1

8 0 3
2 1 4
7 6 5
1 2 3
8 0 4
7 6 5

输出样例 1

5

  • [1 ] 这道问题主要考察:
  1. 对八数码这个东西的理解,以及对这个问题的尝试。
  2. 主要对广度优先搜索/深度优先搜索的理解与运用。
  3. 对于代码量大的难题,细节是最重要的。
  4. 对只是的灵活运用及他的解法,找出其中的规律。

这道题最好画一个图,否则就不很好理解。

  • [ 2] 图解
    -题解-八数码问题_第1张图片
    转换为:
    题解-八数码问题_第2张图片
    途中需要经过以下几个步骤:

  • 将九宫格中的数给转换为图2中的数阵。

  • 左右上下,不能出界,必须达到目标状态。

  • 只能变换数0。

|803-813-013-103-123
|214-204-024-824-804
|765-765-765-765-765
|————运动过程

  • [ 3] 过程解

1.将执行前的初始状态,用来求表示最短路的过程。
2.用执行后的目标状态,来求值。

最后,就不多说,建议去玩玩这个游戏
AC代码:

#include 
using namespace std;
struct node{
int a[3][3];
int x, y;
int t;
bool operator< (const node &x) const{
	for(int i=0;i<3;i++){
		for(int j=0;j<3;j++){
			if(a[i][j]!=x.a[i][j]){
				return a[i][j] st;
queue qu;
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool in(int x, int y){
	return 0 <= x && x < 3 && 0 <= y && y < 3;
}
int bfs(){
	qu.push(START);
	st.insert(START);
	while(!qu.empty()){
	node now=qu.front();
	qu.pop();
	for(int i=0;i<4; i++){
	int tx = now.x + dir[i][0];
	int ty = now.y + dir[i][1];
	if(in(tx,ty)){
		node nxt=now;
		swap(nxt.a[tx][ty], nxt.a[nxt.x][nxt.y]);
		nxt.x=tx;
		nxt.y=ty;
		nxt.t++;
		if(nxt==END){
		return nxt.t;
		}
			if(st.count(nxt) == 0){
				qu.push(nxt);
				st.insert(nxt);
			}
	}
}
}
return -1;
}
int main() {
	for(int i=0;i<3;i++){
		for(int j=0;j<3;j++){
			cin>>START.a[i][j];
			if(START.a[i][j]==0){
				START.x=i;
				START.y=j;
			}
		}
	}
	for(int i=0;i<3;i++){
		for(int j=0;j<3;j++){
			cin>>END.a[i][j];
		}
	}
	cout<

你可能感兴趣的:(题解)