问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22
结题思路:这一题就是纯粹的bfs(),问题就是出在如何保存一个局面?那就是把这个局面映射到一个哈希值,以下代码init_table()和insert_table()就是进行了哈希处理。返回这个排列的大小,即在全部的排列中排第几,其他的就没有了.
AC代码;
# include <stdio.h>
# include <string.h>
# include <algorithm>
# include <queue>
using namespace std;
typedef long long int ll;
struct node{
char a[12];
int cnt;
};
queue<node> q;
int g[5][5], f[12], vis[363000];
void init_table();
int insert_table(char *);
int main(){
int i, j ,k;
char s[12], d[12], ch;
scanf("%s", s);
scanf("%s", d);
for(i=0; i<9; i++){
if(s[i]=='.'){
s[i]='0';break;
}
}
for(i=0; i<9; i++){
if(d[i]=='.'){
d[i]='0';break;
}
}
for(i=1; i<=3; i++){
for(j=1; j<=3 ;j++){
g[i][j]=1;
}
}
node front;
memcpy(front.a, s, sizeof(s));
front.cnt=0;
insert_table(front.a);
q.push(front);
init_table();
while(!q.empty()){
node e=q.front();
int cnt=e.cnt;
char tchar[12];
q.pop();
if(memcmp(e.a, d, sizeof(d))==0){
printf("%d", e.cnt);
return 0;
}
for(i=0; i<9; i++){
if(e.a[i]=='0'){
break;
}
}
int x=i/3+1, y=i%3+1;
if(g[x+1][y]){
memcpy(tchar, e.a, sizeof(e.a));
ch=tchar[i];tchar[i]=tchar[i+3];tchar[i+3]=ch;
if(insert_table(tchar)){
node temp;
temp.cnt=e.cnt+1;
memcpy(temp.a, tchar, sizeof(tchar));
q.push(temp);
}
}
if(g[x-1][y]){
memcpy(tchar, e.a, sizeof(e.a));
ch=tchar[i];tchar[i]=tchar[i-3];tchar[i-3]=ch;
if(insert_table(tchar)){
node temp;
temp.cnt=e.cnt+1;
memcpy(temp.a, tchar, sizeof(tchar));
q.push(temp);
}
}
if(g[x][y-1]){
memcpy(tchar, e.a, sizeof(e.a));
ch=tchar[i];tchar[i]=tchar[i-1];tchar[i-1]=ch;
if(insert_table(tchar)){
node temp;
temp.cnt=e.cnt+1;
memcpy(temp.a, tchar, sizeof(tchar));
q.push(temp);
}
}
if(g[x][y+1]){
memcpy(tchar, e.a, sizeof(e.a));
ch=tchar[i];tchar[i]=tchar[i+1];tchar[i+1]=ch;
if(insert_table(tchar)){
node temp;
temp.cnt=e.cnt+1;
memcpy(temp.a, tchar, sizeof(tchar));
q.push(temp);
}
}
}
printf("-1");
return 0;
}
void init_table(){
f[0]=1;
for(int i=1; i<9; i++){
f[i]=f[i-1]*i;
}
}
int insert_table(char* p){
int cnt;
int sum=0;
for(int i=0; i<9; i++){
cnt=0;
for(int j=i+1; j<9; j++){
if(p[i]>p[j]){
cnt++;
}
}
sum=sum+cnt*f[8-i];
}
if(vis[sum])return 0;
else return vis[sum]=1;
}