洛谷-八数码

105 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

八数码难题

题目描述

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

输入格式

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

输出格式

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

样例 #1

样例输入 #1

283104765

样例输出 #1

4

分析:这是个比较隐晦的BFSBFS,把一个字符串分成三行,然后跟迷宫一个驾驶,然后每个状态记录一下用unorderer——mapunorderer——map,最后在输出一下mp[se];

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string> 
#include <queue>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <stack> 
#include <cmath>
#include <iomanip>
#define ll long long
#define AC return
#define Please 0
using namespace std;
const int N=510;
const double esp=1e-8;
typedef pair<int,int>PII;
typedef unsigned long long ull; 
map<string, pair<char, string>> pre;
unordered_map<string,int>mp;
inline int read(){//快读 
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9'){
        x=x*10+ch-'0'; 
        ch=getchar();
    }
    AC x*f;
} 
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
bool check(int x,int y){
	return (x>=0 && x<=2 && y>=0 && y<=2);
}
string en;
int bfs(string x){
	mp.clear();
	en="123804765";
	queue<string> q;
	q.push(x);
	mp[x]=0;
	while(q.size()){
		string t=q.front();
	    int d=mp[t];
		q.pop();
		int loc=t.find('0');
		int sx=loc/3,sy=loc%3;
		for(int i=0;i<4;i++){
			int nex=sx+dx[i],ney=sy+dy[i];
			if(check(nex,ney)){
				swap(t[nex*3+ney],t[loc]);
				if(!mp.count(t)){
					//cout<<now<<endl;
					mp[t]=d+1;
					//cout<<mp[now]<<" ";
					q.push(t);
				}
				swap(t[nex*3+ney],t[loc]);
			}
		}
	}
}
int n,m,p,cnt=0;
int main(){
	string s;
	cin>>s;
	bfs(s);
	cout<<mp[en];
}

希望能帮助到大家(QAQQAQ)!