历届试题 九宫重排

  历届试题 九宫重排  

时间限制:1.0s   内存限制:256.0MB

      

锦囊1

搜索。

问题描述

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

  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式

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

输出格式

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

样例输入

12345678.
123.46758

样例输出

3

样例输入

13524678.
46758123.

样例输出

22

 参考链接:http://www.cnblogs.com/Ambrose/p/5100750.html

 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct _Node
{
    char tab[3][3];
    int x,y;
    int no;
}Node,*pNode;
int vx[4]={-1,1,0,0};
int vy[4]={0,0,-1,1};
Node res[400000];
int front=0,rear=0;
int vis[4000000],fact[9]; 

void input(pNode start);
void bfs(pNode start,pNode end);
void init_lookup_table();
int try_to_insert(int s);
int main()
{
    Node start,end;
    input(&start);
    input(&end);
    bfs(&start,&end);
    printf("-1\n");
    return 0; 
}
void input(pNode start)
{
    int i,j;
    for(i=0;i<3;i++)
    {
        for(j=0;j<3;j++)
        {
            scanf("%c",&( (start->tab)[i][j] ));
            if((start->tab)[i][j]=='.')
            {
                start->x = i;
                start->y = j;
            }
        }
    }
    start->no = 0;
    getchar();
}
void bfs(pNode start,pNode end)
{
    int i,j;
    char ch;
    pNode tmp;
    init_lookup_table();
    memcpy(&res[rear],start,sizeof(res[rear]));
    try_to_insert(rear); 
    rear++;
    while(front!=rear)
    {
        //printf("%d  ",rear);
        tmp = &res[front];
        if(memcmp(tmp->tab,end->tab,sizeof(end->tab))==0)
        {
            printf("%d\n",tmp->no);
            exit(0);
        }
        int no = tmp->no;
        for(i=0;i<4;i++)
        {
            int xx = tmp->x+vx[i];
            int yy = tmp->y+vy[i];
            if(xx>=0 && xx<3 && yy>=0 && yy<3)
            {
                pNode p = &res[rear];
                memcpy(p,tmp,sizeof(res[front]));
                p->tab[tmp->x][tmp->y] = p->tab[xx][yy];
                p->tab[xx][yy] = tmp->tab[tmp->x][tmp->y];
                p->no = no+1;
                p->x = xx;
                p->y = yy;
                if(try_to_insert(rear))
                {
                    rear++;
                }
            }
        }
        front++;
        //printf("%d  ",rear);
    }
}

void init_lookup_table()
{
    int i;
    fact[0] = 1;
    for(i=1;i<9;i++)
    {
        fact[i] = fact[i-1]*i;
    }
}

int try_to_insert(int s)
{
    int i,j;
    int code = 0;
    for(i=0;i<9;i++)
    {
        int cnt = 0;
        for(j=i+1;j<9;j++)
        {
            if(res[s].tab[j/3][j%3] < res[s].tab[i/3][i%3])
            {
                cnt++;
            }
            code += fact[8-i]*cnt;
        }
    }
    if(vis[code])
    {
        return 0;
    }
    return vis[code] = 1;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值