bfs 宽度优先搜索 八数码问题

该文章介绍了一种使用广度优先搜索(BFS)解决3x3九宫格中寻找最少交换次数使序列变为12345678x的方法。关键在于利用队列和哈希表优化存储,以及处理一维下标与二维坐标的转换。代码示例展示了如何通过状态转移和交换操作来遍历所有可能性。
摘要由CSDN通过智能技术生成

问题介绍:

        在3 * 3的九宫格中存储1、2、3、4、5、6、7、8、x九个元素,x可与其上下左右相邻的数进行交换,求形成以下形式的最少交换次数

123
456
78x

输入格式:

        占一行,相邻的元素之间用空格隔开,将九宫格的初始状态描绘出来。

输出格式:

        一个整数,表示最少的交换次数。

        需要注意可能存在无解的情况。

其实这个题目特别像小时候玩的数字华容道,x就可以看作是九宫格中唯一空缺的位置。

解题思路就是每层遍历x接下来可能交换的位置,这里没什么好说的。需要注意的是,这道题目使用二维数组存储九宫格难以解决(我一开始就是尝试使用二维数组进行存储,但是失败了),使用队列以及哈希表会有非常好的效果。还有一点,因为输入格式只有一行并且我们选择了使用队列1进行存储,而题目的要求是二维的九宫格,所以其中牵扯到一维下表与二维坐标之间的相互对应转化。

存储方式和点坐标的表示真的困扰了我许久。

代码实现:

#include <iostream>
#include <algorithm>
#include <queue> // 队列
#include <unordered_map>

using namespace std;

int bfs(string start)
{
	string end = "12345678x"; // 终点
	
	queue<string> q; //存储九宫格
	unordered_map<string, int> d; // 存储距离
	
	q.push(start);
	d[start] = 0;
	
	int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; // 状态偏移量
	
	while(q.size())
	{
		auto t = q.front();
		q.pop();
		
		int distance = d[t];
		
		if(t == end) return distance;
		
		//状态转移 
		int k = t.find('x');
		int x = k / 3, y = k % 3; // 一维中x的下标对应到二维数组中的坐标
		
		for(int i = 0; i < 4; i ++ ) // 遍历要交换的点
		{
			int a = x + dx[i], b = y + dy[i]; // 要交换的点的坐标
			if(a >= 0 && a < 3 && b >= 0 && b < 3)
			{
				// 交换操作合法,交换x y
				swap(t[k], t[a * 3 + b]); // a * b + 3 二维坐标对应到一维下表
				
				if(!d.count(t))
				{
					d[t] = distance + 1;
					q.push(t);
				}
				
				swap(t[k], t[a * 3 + b]);
			}
		}
	}
	
	return -1;
}

int main()
{
	string start;
	for(int i = 0; i < 9; i ++ )
	{
		char s;
		cin >> s;
		start += s;
	}
	
	cout << bfs(start) << endl;
	
	return 0;
}

参考代码来源:AcWing 845. 八数码 - AcWing

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值