问题 A: 八数码
时间限制: 1 Sec 内存限制: 256 MB提交: 9 解决: 7
[ 提交][ 状态][ 讨论版]
题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入
输入初试状态,一行九个数字,空格用0表示
输出
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)。
样例输入
283104765
样例输出
4
提示
//
// main.cpp
// 问题 A: 八数码
//
// Created by wenhan on 2017/7/28.
// Copyright © 2017年 wenhan. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
int s=0;
struct me{
int c[4][4];
int cur;
int x,y;
}me;
int v[4][4]={{0,0,0,0},{0,1,2,3},{0,8,0,4},{0,7,6,5}};
int t[4][4];
using namespace std;
bool panduan(struct me a)
{
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
if(a.c[i][j]!=v[i][j])
return false;
return true;
}
void bfs()
{
if(panduan(me))
return;
queue<struct me>my;
map<long long,int>mx;
my.push(me);
while (!my.empty()) {
struct me x=my.front();
my.pop();
int ss=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
ss=ss*10+x.c[i][j];
if(mx.count(ss))
continue;
if(panduan(x))
{
me.cur=x.cur;
return;
}
mx[ss]=1;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
if(x.c[i][j]==0)
{
x.x=i;x.y=j;
break;
}
//printf("%d\n",x.cur);
//接下来是4个方向,我人傻,大神请勿喷
if(x.x+1<=3)
{
struct me y;
y=x;
swap(y.c[y.x][y.y], y.c[y.x+1][y.y]);
y.cur++;
my.push(y);
}
if(x.x-1>=1)
{
struct me y;
y=x;
swap(y.c[y.x][y.y], y.c[y.x-1][y.y]);
y.cur++;
my.push(y);
}
if(x.y+1<=3)
{
struct me y;
y=x;
swap(y.c[y.x][y.y], y.c[y.x][y.y+1]);
y.cur++;
my.push(y);
}
if(x.y-1>=1)
{
struct me y;
y=x;
swap(y.c[y.x][y.y], y.c[y.x][y.y-1]);
y.cur++;
my.push(y);
}
}
}
int main() {
char a[11];
scanf("%s",a);
for(int i=1;i<=3;i++)
for (int j=1; j<=3; j++) {
me.c[i][j]=a[s++]-'0';
}
me.cur=0;
s=0;
bfs();
printf("%d\n",me.cur);
// insert code here...
//std::cout << "Hello, World!\n";
return 0;
}