历届试题 九宫重排 蓝桥杯

来源:互联网 发布:淘宝上的跳蛋干净吗 编辑:程序博客网 时间:2024/06/09 14:49
问题描述
  如下面第一个图的九宫格中,放着 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。


0 0
原创粉丝点击