八数码问题(bfs)

 方式一:string存储状态

题目传送门:845. 八数码 - AcWing题库

BFS适用于边权为1的最短路问题 ,而这题要求最少的交换次数,将每一次的九宫格状态当作一个“状态结点”,由当前这个结点可以扩展出其它状态【即 x 可以与其上下左右(若存在的话)交换】,每一种可能的交换都将是bfs“踏出的下一步结点”。

这题难在如何存储状态,并且同一种状态将会有多种方式得出,需要 “ 去重 ” 保存状态,每一个状态对应到达该状态的最短路(即x的交换次数)是多少,于是我们想到用map来存【状态-步数】,同样bfs队列里也加入到达的状态,九宫格的状态可以用字符串来表示。

编码阶段:九宫格转换为字符串存储

解码阶段:字符串转换为九宫格后  ,再加以交换操作

编码和解码的转换通过stirng的下标 与 九宫格的横纵坐标的联系来实现:设字符 x 在string中的下标为t,则在九宫格a中为 a[t/3][t%3] 。(下标都从0开始)同样地,九宫格中某个数字的横纵坐标分别为x和y,则其在sting中存储的下标应为 x*3+y。

本题还学到了swap交换的对象之广泛,可以直接对string中的两个字符做交换。

(此外unordered_map在此题中比普通map要快)

 上代码:

#include<iostream>
#include<queue>
#include<string>
#include<unordered_map>
using namespace std;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};    //下标偏移数组,分别对应x的上右下左
unordered_map<string,int> mp;
queue<string> q;
int bfs(){
	string s;
	while(!q.empty()){
		s=q.front();
		q.pop();
		int stp=mp[s];
		if(s=="12345678x")return stp;
		int t=s.find('x');  //寻找下标
		int x=t/3, y=t%3;   //由下标得到横纵坐标
		for(int i=0,tx,ty;i<4;i++){
			tx=x+dx[i];
			ty=y+dy[i];
			if(tx<0||tx>=3||ty<0||ty>=3)continue;//注意此处是>=3不是>3
			int t2=tx*3+ty;     //转换为横纵坐标
			swap(s[t],s[t2]);
			if(!mp.count(s)){   //判重
				mp[s]=stp+1;
				q.push(s);
			}
			swap(s[t],s[t2]);
		}
	}
	return -1;
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	string s,t;
	for(int i=0;i<9;i++){
		cin>>t;
		s+=t;
	}
	q.push(s);
	mp[s]=0;
	cout<<bfs();
	return 0;
}

 

 方式二:用一个数(long long)存储状态

当然,这个适合输入全是数的情况(如x换为0)

题目传送门:P1379 八数码难题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 

 犯过的错就是,注意横纵坐标对应,从0开始存的就横纵坐标<3,从1开始存的就<=3 QAQ

直接上代码:

#include<iostream>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
map<ll,int> mp;
queue<ll> q;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1},a[5][5];
ll t;
int bfs(){
	while(!q.empty()){
		t=q.front();
		q.pop();
		int stp=mp[t], x, y;
		if(t==123804765)return stp;
		//数转矩阵 
		for(int i=3;i>0;i--){
			for(int j=3;j>0;j--){
				a[i][j]=t%10;
				t/=10;
				if(!a[i][j])x=i, y=j;
			}
		}
		for(int i=0,tx,ty;i<4;i++){
			tx=x+dx[i];
			ty=y+dy[i];
			if(tx<1||tx>3||ty<1||ty>3)continue;
			swap(a[x][y],a[tx][ty]);
			//矩阵转数
			t=0;
			for(int i=1;i<=3;i++){
				for(int j=1;j<=3;j++){
					t=t*10+a[i][j];
				}
			} 
			if(!mp.count(t)){
				mp[t]=stp+1;
				q.push(t);
			}
			swap(a[x][y],a[tx][ty]);
		}
	}
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);//可忽略,关同步流来提速的
	cin>>t;
	q.push(t);
	mp[t]=0;
	cout<<bfs();
	return 0;
}

相关推荐

  1. 基础算法bfs -剪枝问题

    2024-04-08 09:16:04       49 阅读
  2. 1076. 迷宫问题(bfs,记录路径)

    2024-04-08 09:16:04       67 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-08 09:16:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-08 09:16:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-08 09:16:04       87 阅读
  4. Python语言-面向对象

    2024-04-08 09:16:04       96 阅读

热门阅读

  1. 数据结构之栈(LIFO)

    2024-04-08 09:16:04       35 阅读
  2. Golang基础-9

    2024-04-08 09:16:04       30 阅读
  3. spring介绍

    2024-04-08 09:16:04       33 阅读
  4. 鼎盛合方案设计——汽车轮胎气压监测方案

    2024-04-08 09:16:04       40 阅读
  5. 全球化业务的网络安全挑战

    2024-04-08 09:16:04       38 阅读
  6. gcc/g++:预编译阶段查看模块生成目标的直接依赖

    2024-04-08 09:16:04       36 阅读
  7. 【c++20】金山云liuguang引擎

    2024-04-08 09:16:04       36 阅读
  8. MongoDB数据库服务

    2024-04-08 09:16:04       37 阅读
  9. 每日一题:三数之和

    2024-04-08 09:16:04       42 阅读