【题目描述】
这是一个很古老的游戏了:有一个3 × 3的活动拼盘(如下图),方格上写有0~8这九个数字。例如:3 7 5
2 6 1
4 8 0
利用拼盘背后的旋钮,游戏者每次可以进行以下两种操作之一:1.将拼盘外围的8个方格按顺时针挪一个位置。2.将中间一行向右移动一个位置,最右边的方格被移到最左边。例如:给你一个拼盘的初始状态,你能用最少的操作次数把拼盘变成下图所示的目标状态吗?
0 1 2
3 4 5
6 7 8
【输入格式】
本题有多组测试数据。输入文件中包含三行三列九个数,同行的相邻两数用空格隔开,表示初始状态每个方格上的数字。初始状态不会是目标状态。
【输出格式】
如果目标状态无法达到,则输出“UNSOLVABLE”(引号不输出)。否则,输出最少的操作次数。
多组数据从目标状态反搜预处理每一个状态的最小步数,康拓展开去重,询问时判断有无,输出即可。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct que
{
int a[4][4];
int d;
};
int mu[4][4],qi[4][4],dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int f[10]={1,1,2,6,24,120,720,5040,40320,326880};
bool h[10000005];
int ans[10000005];
int key1,key2;
queue<que> q;
void init()
{
qi[1][2]=1; qi[1][3]=2; qi[2][1]=3;
qi[2][2]=4; qi[2][3]=5; qi[3][1]=6;
qi[3][2]=7; qi[3][3]=8;
}
int key(int a[][4])
{
int ans=0;
for(int i=3;i<=11;i++)
{
int tmp=0;
for(int j=i+1;j<=11;j++)
{
if(a[i/3][i%3+1]>a[j/3][j%3+1]) tmp++;
}
ans+=tmp*f[11-i];
}
return ans;
}
bool hash(int a[][4])
{
key1=key(a);
if(h[key1]) return false;
else return true;
}
bool bfs()
{
que r;
memcpy(r.a,qi,sizeof(qi));
r.d=0;
q.push(r);
key1=key(qi);
h[key1]=true;
ans[key1]=0;
while(!q.empty())
{
que u=q.front();
/* for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
printf("%d ",u.a[i][j]);
}
printf("\n");
}
getchar();*/
q.pop();
swap(u.a[2][1],u.a[2][3]);
swap(u.a[2][1],u.a[2][2]);
if(hash(u.a))
{
memcpy(r.a,u.a,sizeof(u.a));
r.d=u.d+1;
h[key1]=true;
ans[key1]=u.d+1;
q.push(r);
}
swap(u.a[2][1],u.a[2][2]);
swap(u.a[2][1],u.a[2][3]);
swap(u.a[1][1],u.a[2][1]);
swap(u.a[1][1],u.a[3][1]);
swap(u.a[1][1],u.a[3][2]);
swap(u.a[1][1],u.a[3][3]);
swap(u.a[1][1],u.a[2][3]);
swap(u.a[1][1],u.a[1][3]);
swap(u.a[1][1],u.a[1][2]);
if(hash(u.a))
{
h[key1]=true;
ans[key1]=u.d+1;
memcpy(r.a,u.a,sizeof(u.a));
r.d=u.d+1;
q.push(r);
}
}
}
int main()
{
memset(ans,-1,sizeof(ans));
init();
bfs();
while(~scanf("%d",&mu[1][1]))
{
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
{
if(i==1&&j==1) continue;
scanf("%d",&mu[i][j]);
}
key1=key(mu);
if(ans[key1]>=0) printf("%d\n",ans[key1]);
else printf("UNSOLVABLE\n");
}
}