您的位置:首页 > 其它

历届试题 九宫重排 蓝桥杯

2017-03-04 12:56 363 查看
问题描述

  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。





  我们把第一个图的局面记为:12345678.

  把第二个图的局面记为:123.46758

  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。

  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式

  输入第一行包含九宫的初态,第二行包含九宫的终态。

输出格式

  输出最少的步数,如果不存在方案,则输出-1。

样例输入

12345678.

123.46758

样例输出

3

样例输入

13524678.

46758123.

样例输出

22

广搜

队列,hash验重

#include<cstdio>
#include<cstring>
const int state_maxsize=400010;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
typedef int state[9];
state q[state_maxsize],goal;
int dist[state_maxsize]={0};
const int hash_size=10000000;
int head[hash_size]={0},next[state_maxsize];
int hash(state &x){
int sum=0;
for(int i=0;i<9;i++)
sum=sum*10+x[i];
return sum%hash_size;
}
int try_to_sert(int x){
int h=hash(q[x]);
int u=head[h];
while(u){
while(memcmp(q[u],q[x],sizeof(q[x]))==0){
return 0;
}
u=next[u];
}
next[x]=u;
head[h]=x;
return 1;
}
int bfs(){
int front=1;
int rear=2;
while(front<rear){
state&s=q[front];
if(memcmp(goal,s,sizeof(s))==0)return front;
int z=0;
while(s[z]!=0)z++;
int x=z/3;
int y=z%3;
for(int i=0;i<4;i++){
int newx=x+dx[i];
int newy=y+dy[i];
int newz=newx*3+newy;
if(newx>=0&&newx<3&&newy>=0&&newy<3){
state&t=q[rear];
memcpy(t,s,sizeof(s));
t[newz]=s[z];
t[z]=s[newz];
dist[rear]=dist[front]+1;
if(try_to_sert(rear))rear++;

}
}
front++;
}
return 0;
}
int main(){
char c;
for(int i=0;i<9;i++){
if((c=getchar())!='.')
q[1][i]=c-'0';
else
q[1][i]=0;
}
getchar();
for(int i=0;i<9;i++){
if((c=getchar())!='.')
goal[i]=c-'0';
else
goal[i]=0;
}
if(int y=bfs())
printf("%d\n",dist[y]);
else
printf("-1\n");
}



双向搜索

与单向广搜的区别,在于把起点终点依次放入队列,然后你一层,我一层地遍历;验重的时候,分辨是于哪个出发点出发的路径重叠。

#include<cstdio>
#include<cstring>
const int state_maxsize=400010;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
typedef int state[9];
state q[state_maxsize];
int dist[state_maxsize]={0};
int root[state_maxsize]={0};
const int hash_size=10000000;
int head[hash_size]={0},next[state_maxsize];
int hash(state &x){
int sum=0;
for(int i=0;i<9;i++)
sum=sum*10+x[i];
return sum%hash_size;
}
int try_to_sert(int x){
int h=hash(q[x]);
int u=head[h];
while(u){
while(memcmp(q[u],q[x],sizeof(q[x]))==0){
if(root[u]==root[x])
return 0;
else
return u;
}
u=next[u];
}
next[x]=u;
head[h]=x;
return 1;
}
int bfs(){
root[1]=1;
root[2]=2;
int front=1;
int rear=3;
while(front<rear){
state&s=q[front];
int z=0;
while(s[z]!=0)z++;
int x=z/3;
int y=z%3;
for(int i=0;i<4;i++){
int newx=x+dx[i];
int newy=y+dy[i];
int newz=newx*3+newy;
if(newx>=0&&newx<3&&newy>=0&&newy<3){
state&t=q[rear];
memcpy(t,s,sizeof(s));
t[newz]=s[z];
t[z]=s[newz];
root[rear]=root[front];
dist[rear]=dist[front]+1;
switch(int u=try_to_sert(rear)){
case 0:break;
case 1:rear++;break;
default:return dist[u]+dist[rear];
}
}
}
front++;
}
return 0;
}
int main(){
char c;
for(int i=0;i<9;i++){
if((c=getchar())!='.')
q[1][i]=c-'0';
else
q[1][i]=0;
}
getchar();
for(int i=0;i<9;i++){
if((c=getchar())!='.')
q[2][i]=c-'0';
else
q[2][i]=0;
}
if(int y=bfs())
printf("%d\n",y);
else
printf("-1\n");
}



蓝桥oj上单向花了156ms,双向花了15ms。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: