UVA-10085 - The most distant state

跟白书上介绍的8迷问题十分相似,只是这道题需要记录移动的步骤,而且是求最大可移动的步数。

思路:1.保存每一步的状态。2.HASH查找有无重复状态。3.记录最远能达到的状态。主要算法:利用BFS遍历所有状态。

#include<stdio.h>
#include<math.h>
#include<string.h>
#define MAXSTATE 1000003
int origin[3][3],current[3][3],final[3][3];
int maxstep;
char order[100];
int head[MAXSTATE],next[MAXSTATE];
typedef struct que{
    int state[3][3];
    int step;
    char next[100];
}Q;    
Q Queue[MAXSTATE+1];
int dx[4]={0,0,-1,1};
int dy[4]={-1,1,0,0};//L,R,U,D
void Output()
{
    int i,j;
    for(i=0;i<3;i++)
    {
        printf("%d",final[i][0]);
        for(j=1;j<3;j++)
        {
            printf(" %d",final[i][j]);
        }
        printf("\n");
    }        
    printf("%s\n\n",order);
}    
int getBlank(int *x,int *y)
{
    int i,j;
    for(i=0;i<3;i++)
    {
        for(j=0;j<3;j++)
        {
            if(current[i][j]==0)
            {
                *x=i;*y=j;
                return 1;
            }
        }
    }       
    return 0;
}   
void addOrder(int n,int state)
{
    switch(state)
    {
        case 0:
            strcat(Queue[n].next,"L");
            break;
        case 1:
            strcat(Queue[n].next,"R");
            break;
        case 2:
            strcat(Queue[n].next,"U");
            break;
        case 3:
            strcat(Queue[n].next,"D");
            break;
    }
}  
int hash(int n)
{
    int i,j,v=0;
    for(i=0;i<3;i++)
    {
        for(j=0;j<3;j++)
        {
            v=v*10+Queue[n].state[i][j];
        }
    }
    return v%MAXSTATE;
}            
            
int isExist(int n)
{
    int h,u;
    h=hash(n);
    u=head[h];
    while(u)
    {
        if(memcmp(Queue[u].state,Queue[n].state,sizeof(Queue[n].state))==0)return 1;
        u=next[u];
    }    
    next[n]=head[h];
    head[h]=n;
    return 0;
}                        
int BFS()
{
    int i,j,k;
    int ox,oy,nx,ny,front=0,rear=0;
    memcpy(Queue[rear].state,origin,sizeof(origin));
    memset(Queue[rear].next,0,sizeof(Queue[rear].next));
    memset(head,0,sizeof(head));
    Queue[rear++].step=0;
    while(front<rear)
    {
        memcpy(current,Queue[front].state,sizeof(current));//出队 
        getBlank(&ox,&oy);//获取空格位置
        for(i=0;i<4;i++)
        {
            nx=ox+dx[i];ny=oy+dy[i];//移动空格 
            if(nx>=0&&nx<3&&ny>=0&&ny<3)//检测是否可移动
            {
                //移动
                current[ox][oy]=current[nx][ny];
                current[nx][ny]=0;
                //Hash检测状态是否重复
                 memcpy(Queue[rear].state,current,sizeof(current)); 
                if(!isExist(rear))
                {
                    //入队,记录移动步骤和步数 
                    memcpy(Queue[rear].next,Queue[front].next,sizeof(Queue[front].next));
                    addOrder(rear,i);
                    Queue[rear].step=Queue[front].step+1;
                    if(maxstep<Queue[rear].step)
                    {
                        maxstep=Queue[rear].step;
                        memcpy(order,Queue[rear].next,sizeof(Queue[rear].next));
                        memcpy(final,Queue[rear].state,sizeof(Queue[rear].state));
                    }  
                    rear++;  
                }    
                //恢复
                current[nx][ny]=current[ox][oy];
                current[ox][oy]=0;         
            }
        } 
        front++; 
    }      
}                
int main()
{
    int cases,puzzle=0;
    scanf("%d",&cases);
    int i,j,k;
    while(cases--)
    {
        maxstep=0;
        for(i=0;i<3;i++)
        {
            for(j=0;j<3;j++)
            {
                scanf("%d",&origin[i][j]);
            }    
        }
        BFS();
        printf("Puzzle #%d\n",++puzzle);
        Output();
    } 
    return 0;
}         
        




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值