资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22
/用bfs+康托去重,见代码/
在这里插入代码片
#include<iostream>
#include<string.h>
#include<queue>
#define swap(a,b) {int t = a;a = b;b = t;}
using namespace std;
int mv[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
int visit[362880] = {0};
int start[9];
int end[9];
long int fac[] = {1,1,2,6,24,120,720,5040,40320,362880}; //康托展开会用到的数据 0~9 的阶乘
struct node{ //定义队列里的类型node
int state[9];
int dis;
};
queue<node>q;
int f(int a[],int n) //康托展开去重,不会的可以百度找找^-^
{
long result = 0;
for(int i=0;i<n;i++){
int c = 0;
for(int j=1+i;j<n;j++){
if(a[i] > a[j]) //在区间[j,n-1]中找比a[i]大的数字有几个
c++;
}
result += c*fac[n-i-1];
} //最终result就是这个数字在0~9全排列中的位置
if(visit[result])
return 0;
else{
visit[result] = 1;
return 1;
}
}
int bfs()
{
node head;
memcpy(head.state,start,sizeof(start)); //复制起点的状态
head.dis = 0;
q.push(head); //起点进队
f(head.state,9);
while(!q.empty())
{
node newnode = q.front(); //访问队头
q.pop(); //出队
int pos; //找到数字 0 所在的位置
for(int i=0;i<9;i++){
if(newnode.state[i] == 0){
pos = i;
break;
}
}
int x = pos/3; //转化为二维坐标
int y = pos%3;
for(int i=0;i<4;i++){
int nx = x+mv[i][0];
int ny = y+mv[i][1];
int nz = nx*3+ny; //转化为一维坐标
if(nx<3&&nx>=0&&ny<3&&ny>=0){
node newhead;
memcpy(&newhead,&newnode,sizeof(struct node)); //复制出队元素的状态
newhead.dis += 1;
swap(newhead.state[pos],newhead.state[nz]); //进行交换
if(memcmp(newhead.state,end,sizeof(end)) == 0) //如果与结束态相同就结束
return newhead.dis;
if(f(newhead.state,9)) //利用康拓去重判断这个状态是否出现过
q.push(newhead); //没出现就进队
}
}
}
return -1; //转换不到结束态就返回-1
}
int main()
{
int s;
string s1,s2;
cin>>s1;
getchar();
cin>>s2;
for(int i=0;i<9;i++){
if(s1[i] == '.'){
start[i] = 0;
s = i;
}
else
start[i] = s1[i] - '0';
if(s2[i] == '.')
end[i] = 0;
else
end[i] = s2[i] - '0';
}
int ans = bfs();
cout<<ans<<endl;
}