题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入输出格式
输入格式:输入初始状态,一行九个数字,空格用0表示
输出格式:只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
输入输出样例
输入样例#1:
283104765
输出样例#1:
4
用这道题复习了下bfs以及hash
显然这题求最小步数应当要用bfs
此处直接存了八数码的九个位置的数(当然也可以转为一个九位数,在九位数上进行操作)
然后把八数码转换为一个九位数,用hash来判重。(九位数太大,开一个10^10的数组浪费太多空间并且也开不下,而所有可能情况只有 9! 种)
第一次写没有注意到了边界
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
const int hn = 199999;
const int fx[4] = {1,-1,0,0};
const int fy[4] = {0,0,1,-1};
struct data{
int a[3][3],n;
data(int n = 1){
memset(a,0,sizeof(a));
}
bool operator == (const data &b){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(a[i][j] != b.a[i][j]) return false;
}
}
return true;
}
};
data s,e;
int N;
queue<data> q;
vector<LL> h[hn];
inline int get(){
char c;
while((c = getchar()) < '0' || c > '9');
int cnt = c - '0';
while((c = getchar()) >= '0' && c <= '9') cnt = cnt * 10 + c - '0';
return cnt;
}
inline LL cal(data a){
LL ans = 0;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
ans = ans * 10 + a.a[i][j];
}
}
return ans;
}
inline void hs(LL a){
int k;
k = a % hn;
h[k].push_back(a);
return;
}
inline bool judge(LL a){
int k;
k = a % hn;
for(int i = 0; i < h[k].size(); i++){
if(h[k][i] == a) return true;
}
return false;
}
int main(){
#ifdef lwy
/* #else
freopen(".in","r",stdin);
freopen(".out","w",stdout);*/
#endif
e.a[0][0] = 1; e.a[0][1] = 2; e.a[0][2] = 3;
e.a[1][0] = 8; e.a[1][1] = 0; e.a[1][2] = 4;
e.a[2][0] = 7; e.a[2][1] = 6; e.a[2][2] = 5;
N = get();
for(int i = 2; i >= 0; i--){
for(int j = 2; j >= 0; j--){
s.a[i][j] = N % 10;
N /= 10;
}
}
q.push(s);
hs(cal(s));
while(!q.empty()){
data f = q.front(); q.pop();
int px,py;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(f.a[i][j] == 0){
px = i; py = j;
break;
}
}
}
for(int i = 0; i < 4; i++){
int tx = px + fx[i]; int ty = py + fy[i];
if(tx < 0 || tx > 2 || ty < 0 || ty > 2) continue; //
data d = f; int p;
d.n = f.n + 1;
p = d.a[px][py];
d.a[px][py] = d.a[tx][ty];
d.a[tx][ty] = p;
if(d == e){
printf("%d",d.n);
return 0;
}
if(!judge(cal(d))){
q.push(d);
hs(cal(d));
}
}
}
return 0;
}