P1379 八数码难题

❤作者:那些年丶我们逃过的课

❤博客主页:那些年丶我们逃过的课的博客_CSDN博客-c++题目,c++学习记录,c++小游戏领域博主

❤码云gitee:我的码云 - Gitee.com

❤期待你的关注,如果觉得还可以的话,可以点赞评论支持一下,每个评论我都会回访的🎉

八数码难题

题目描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入格式

输入初始状态,一行九个数字,空格用0表示

输出格式

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

样例 #1

样例输入 #1

283104765

样例输出 #1

4

使用 BFS搜索,每当搜索到一个新的状态时,就将这个新的状态放入队列内
然后存储 0 的位置,以便于以后的搜索
优化:
用一维储存,比二维储存更加方便
那么就要在每次交换时,把一维转换为二维,交换位置后再转为一维储存
就能达到优化的效果了

#include<bits/stdc++.h>
using namespace std;
map<int,bool> mp;	//建立映射 
int ed=123804765;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};	//状态偏移量 
queue< pair <int,int> >q;	//队列	first表示状态	second表示步数 

int move(int st,int t){
	int temp[4][4],zx,zy;
	for(int i=3;i>=1;i--){
		for(int j=3;j>=1;j--){
			temp[i][j]=st%10;
			if(temp[i][j]==0)	zx=i,zy=j; 
			st/=10;
		}
	}
	int nx=zx+dx[t];
	int ny=zy+dy[t];
	if(!(nx>=1&&nx<=3&&ny>=1&&ny<=3)){
		return 0;		//判断0移动后的位置是否合法 
	}
	swap(temp[nx][ny],temp[zx][zy]);	//交换位置 
	int res=0;
	for(int i=1;i<=3;i++){
		for(int j=1;j<=3;j++){
			res=res*10+temp[i][j];
		}
	}
	return res;
}

void bfs(int bg){
	q.push(make_pair(bg,0));
	mp[bg]=1;
	while(!q.empty()){
		int hx=q.front().first;		//取出队头的状态 
		int hs=q.front().second;	//取出到达该状态的步数
		q.pop();	//队头元素出队
		for(int i=0;i<4;i++){
			int nx=move(hx,i);	//获得了新的状态
			int ns=hs+1;
			if(nx&&mp[nx]==0){	//验证状态合法性 
				mp[nx]=1;
				if(nx==ed){
					cout<<ns;
					return;	//判断是否达到目标状态 
				}
				q.push(make_pair(nx,ns));	//新状态入队
			}
		}
	}
	cout<<0;	//考虑目标状态与初始状态相同的情况
	return;
}

int main(){
	int bg;
	cin>>bg;
	bfs(bg);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值