历届试题 九宫重排 时间限制:1.0s 内存限制:256.0MB 锦囊1锦囊2锦囊3问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。输入格式 输入第一行包含九宫的初态,第二行包含九宫的终态。输出格式 输出最少的步数,如果不存在方案,则输出-1。样例输入12345678.
123.46758样例输出3样例输入13524678.
46758123.样例输出22
这道题目用了字典树来判重;
刚开始做的时候把数组开成了9,大意了,以后一定看清楚数组范围;
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
using namespace std;
typedef struct node
{
int d;
struct node*next[9];
}Node;
typedef struct
{
int step;
char str[10];
}M;
Node *head;
queue<M> q;
int dir[4] = {-1, 1, 3, -3}, f;
char a[10], b[10];
void init_node(Node **p, int j)
{
int i;
*p = (Node *)malloc(sizeof(Node));
(*p)->d = j;
for(i = 0; i < 9; i++)
{
(*p)->next[i] = NULL;
}
}
int create_tree(char *a)
{
Node *p, *temp = head;
int i, flag = 1,j;
for(i = 0; i < 9;i++)
{
if(a[i] == '.')
{
j = 0;
}
else
{
j = a[i] - 48;
}
if( !temp->next[j])//如果j这个值在树中没有那么这整个值就没有出现过;创建结点把这个值存入树中;
{
flag = 0;
init_node(&p, j);
temp->next[j] = p;
}
temp = temp->next[j];
}
return flag;//flag为0说明这个状态没有出现过;
}
int get_pos(char *a)
{
int i;
for(i = 0; i < 9; i++)
{
if(a[i] == '.')
{
return i;
}
}
}
void bfs()
{
int i, pos,npos, j;
M p, t;
while(!q.empty())
{
p = q.front();
q.pop();
pos = get_pos(p.str);
if(strcmp(p.str,b)== 0)
{
f = 1;
printf("%d\n", p.step);
return;
}
for(i = 0 ;i < 4; i++)
{
if((pos % 3 == 0&& dir[i] == -1) || (pos %3 == 2 && dir[i] == 1))
{
continue;
}
npos = pos + dir[i];
if(npos < 0 || npos > 8)
{
continue;
}
strcpy(t.str, p.str);
t.str[pos] = t.str[npos];
t.str[npos] = '.';
j = create_tree(t.str);
if(j == 0)
{
t.step = p.step + 1;
if(memcmp(t.str,b,sizeof(b))== 0)
{
f = 1;
printf("%d\n", t.step);
return;
}
q.push(t);
}
}
}
}
int main()
{
M p;
int i,j;
while(scanf("%s %s", a,b) != EOF)
{
f = 0;
while(!q.empty())
{
q.pop();
}
init_node(&head, 0);
j = create_tree(a);
strcpy(p.str,a);
p.step = 0;
q.push(p);
bfs();
if(f == 0)
printf("-1\n");
}
return 0;
}