问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
123.46758
样例输出
3
样例输入
13524678.
46758123.
46758123.
样例输出
22
这个题更好的办法应该是双向广搜。还没看,以后学会了再更。
这里用的是普通的广搜,需要注意的就是标记。从前简单的搜索,只用vis数组标记这个点有没有走过就行,而这个题需要标记的是状态,本以为用map可以,结果map超时,
这里我用的是字典树,练习一下。。。用vis函数标记此状态有没有经历过。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <queue>
using namespace std;
typedef struct
{
int step;
char s[10];
}node;
typedef struct tnode
{
struct tnode *next[9];
}tnode;
tnode *head = (tnode *)malloc(sizeof(tnode));
char b[10], e[10];
int dirx[4] = {1,-1,3,-3};
int vis(char a[])
{
int flag = 1, i, j;
tnode *root = head;
for(i = 0 ; a[i] != '\0' ; i++)
{
if(root->next[a[i]-'0'] == NULL)
{
flag = 0;
tnode *v = (tnode*)malloc(sizeof(tnode));
for(j = 0 ; j < 9 ; j++)
v->next[j] = NULL;
root->next[a[i]-'0'] = v;
}
root = root->next[a[i]-'0'];
}
return flag;
}
int bfs()
{
queue<node> q;
node u, v;
int i, pos, vi, newpos;
strcpy(u.s, b);
vi = vis(u.s);
u.step = 0;
q.push(u);
while(!q.empty())
{
u = q.front();
q.pop();
if(strcmp(u.s, e) == 0)
return u.step;
for(i = 0 ; i < 9 ; i++)
if(u.s[i] == '0')
{
pos = i;
break;
}
for(i = 0 ; i < 4 ; i++)
{
newpos = pos + dirx[i];
if(newpos < 0 || newpos > 8)
continue;
if(pos % 3 == 2 && dirx[i] == 1 || pos % 3 == 0 && dirx[i] == -1)//这个必须有,在两竖边的数在进行+1-1运算时算出来的newpos虽然是在0-8之间,但是这个运算并不现实,不能从2直接到3.
continue;
v.step = u.step + 1;
strcpy(v.s, u.s);
v.s[pos] = v.s[newpos];//从前那给点变为newpos点的值,newpos变为0
v.s[newpos] = '0';
if(vis(v.s) == 0)
q.push(v);
}
}
return -1;
}
int main()
{
int i;
for(i = 0 ; i < 9 ; i++)
head->next[i] = NULL;
scanf("%s %s", b, e);
if(strcmp(b, e) == 0)
{
printf("0\n");
return 0;
}
for(i = 0 ; i < 9 ; i++)
{
if(b[i] == '.')
b[i] = '0';
if(e[i] == '.')
e[i] = '0';
}
printf("%d\n", bfs());
return 0;
}