UVA - 704 - Colour Hash

题意:类似于魔方的那种智力玩具(不过这个是二维的),通过旋转与最后状态匹配即可。编号顺序:左轮顺时针,右轮逆时针。
思路:1.BFS,每转一次记录一个状态,利用HASH判重。
         2.超过16步就退出。
目标状态:   0 3 4 3 0 5 6 5 0 1 2 1 0 7 8 7 0 9 10 9 0 1 2 1
旋转一次的状态(方便写出旋转函数):
LWC:         2 1 0 3 4 3 0 5 6 5 0 1 0 7 8 7 0 9 10 9 0 5 0 1
RWC:        0 3 4 3 0 5 6 5 0 1 0 7 8 7 0 9 10 9 0 1 2 1 0 7
LWCC:      4 3 0 5 6 5 0 1 2 1 0 3 0 7 8 7 0 9 10 9 0 1 0 3
RWCC:     0 3 4 3 0 5 6 5 0 9 0 1 2 1 0 7 8 7 0  9 10 9 0 1
实现了以上思路后发现程序的状态还是多得装不下,第二组SAMPLE就过不了,把自己的小Y卡得不行,后来去论坛上看了说存8步,我还是没看懂什么意思,又百度了一下,看到了双向BFS,于是终于得到了算法。从最终状态开始走9步,初始状态再走7步,若有重合状态,则在16步及其内可到达。
#include<stdio.h>
#include<string.h>
#define MAXSIZE 1000003
#define FORWARD 1
#define BACKWARD 2
int head[MAXSIZE],next[MAXSIZE];
int backhead[MAXSIZE],backnext[MAXSIZE];
const int final[24]={0,3,4,3,0,5,6,5,0,1,2,1,0,7,8,7,0,9,10,9,0,1,2,1};//final state
int origin[24],cur[24];//origin state and current state
int front,rear,flag,back;
typedef struct s
{
    int state[24];
    int step;
    int action,fa;
}ST;
ST Save[MAXSIZE],BackSave[MAXSIZE];
void Initial()
{
    int i;    
    memset(Save[0].state,0,sizeof(Save[0].state));
    memset(BackSave[0].state,0,sizeof(BackSave[0].state));
    BackSave[0].step=0;
    Save[0].step=0;
    Save[0].fa=BackSave[0].fa=-1;
    BackSave[0].action=Save[0].action=0;
}    
int hash(int state[])
{
    int i,j,v=0,tmp[6];
    memset(tmp,0,sizeof(tmp));
    for(i=0;i<6;i++)
    {
        for(j=0;j<4;j++)tmp[i]+=state[i*4+j];
        v=v*10+tmp[i];
        v%=21474331;
    }
    return v%MAXSIZE;    
}    
int isExist(int n)
{
    int h,u,bh,bu;
    h=hash(Save[n].state);
    u=head[h];
    bh=h;
    bu=backhead[bh];//Check whether current state can be found in BackSave array
    if(!memcmp(BackSave[bh].state,Save[n].state,sizeof(Save[n].state)))
    {
        flag=n;
        back=bh;
        return 1;
    } 
    while(bu)
    {
        if(!memcmp(BackSave[bu].state,Save[n].state,sizeof(Save[n].state)))
        {
            flag=n;
            back=bu;
            return 1;
        }         
        bu=backnext[bu]; 
    }
    while(u)
    {
              
        if(!memcmp(Save[u].state,Save[n].state,sizeof(Save[n].state)))
        {
            return 1;
        }    
        u=next[u];
    }
    next[n]=head[h];
    head[h]=n;
    return 0;
}  
int isBackExist(int n)
{
    int h,u;
    h=hash(BackSave[n].state);
    u=backhead[h];
    while(u)
    {
        if(!memcmp(BackSave[u].state,BackSave[n].state,sizeof(BackSave[n].state)))
        {
            return 1;
        }    
        u=backnext[u];
    }
    backnext[n]=backhead[h];
    backhead[h]=n;
    return 0;
}        
int Insert(int mode,int order)//Save a state
{
    if(order==FORWARD)
    {
        Save[rear].action=mode;
        Save[rear].fa=front;
        if(!isExist(rear))
        {
            Save[rear].step=Save[front].step+1;
            if(Save[rear].step>7)return 0;              
            rear++;
        } 
    }
    else
    {
        
        if(!isBackExist(rear))
        {
            BackSave[rear].action=mode;
            BackSave[rear].fa=front;
            BackSave[rear].step=BackSave[front].step+1;
            if(BackSave[rear].step>9)return 0;            
            rear++;
        } 
    }           
    return 1;
}
void OutPut(int n)
{
    if(n==-1||!Save[n].action)return;
    OutPut(Save[n].fa);
    printf("%d",Save[n].action);
}       
void OrderOutPut(int n)
{
    if(n==-1||!BackSave[n].action)return;    
    printf("%d",BackSave[n].action);
    OrderOutPut(BackSave[n].fa);
}
int LWC(int n,int state[],int order)//Left Wheel Clockwise rotation
{//2 1 0 3 4 3 0 5 6 5 0 1 0 7 8 7 0 9 10 9 0 5 0 1
    if(flag>=0)return 1;
    int i,j,k;
    for(i=0;i<12;i++)
    {
        state[i]=cur[(i+10)%12];
    }
    for(i=12;i<24;i++)
    {
        state[i]=cur[i];
        if(i>20)state[i]=state[i%12];
    }  
    if(!Insert(n,order))return 0;   
    return 1;
}    
int RWC(int n,int state[],int order)//Right Wheel Clockwise rotation
{// 0 3 4 3 0 5 6 5 0 1 0 7 8 7 0 9 10 9 0 1 2 1 0 7
    if(flag>=0)return 1;
    int i,j,k;
    for(i=0;i<9;i++)
    {
        state[i]=cur[i];
    }
    for(i=9;i<24;i++)
    {
        state[i]=cur[(i+2)%24];
        if(i>20)state[i]=state[i-12];
    }  
    if(!Insert(n,order))return 0;   
    return 1;
}
int LWCC(int n,int state[],int order)//Left Wheel Counter-Clockwise rotation
{// 4 3 0 5 6 5 0 1 2 1 0 3 0 7 8 7 0 9 10 9 0 1 0 3
    if(flag>=0)return 1;
    int i,j,k;
    for(i=0;i<12;i++)
    {
        state[i]=cur[(i+14)%12];
    }
    for(i=12;i<24;i++)
    {
        state[i]=cur[i];
        if(i>20)state[i]=state[i%12];
    }  
    if(!Insert(n,order))return 0;   
    return 1;
}
int RWCC(int n,int state[],int order)//Right Wheel Counter-Clockwise rotation
{//0 3 4 3 0 5 6 5 0 9 0 1 2 1 0 7 8 7 0 9 10 9 0 1
    if(flag>=0)return 1;
    int i,j,k;
    for(i=0;i<9;i++)
    {
        state[i]=cur[i];
    }
    for(i=9;i<24;i++)
    {
        if(i<=13)state[i]=cur[i+10];
        if(i>13&&i<=20)state[i]=cur[i-2];
        if(i>20)state[i]=state[i-12];
    }  
    if(!Insert(n,order))return 0;   
    return 1;
}  
void BackBFS()
{//save final state to middle state(about 9 steps)
    front=rear=0;
    memcpy(BackSave[rear++].state,final,sizeof(final));
    while(front<rear)
    {  
        memcpy(cur,BackSave[front].state,sizeof(cur));
        if(!LWC(3,BackSave[rear].state,BACKWARD))break;
        if(!RWC(4,BackSave[rear].state,BACKWARD))break;
        if(!LWCC(1,BackSave[rear].state,BACKWARD))break;
        if(!RWCC(2,BackSave[rear].state,BACKWARD))break;
        front++;
    }
}              
void BFS()
{    
    memset(head,0,sizeof(head));
    memset(next,0,sizeof(next));
    front=rear=0;
    memcpy(Save[rear++].state,origin,sizeof(origin));
    isExist(front);
    if(flag>=0)
    {  
        OutPut(flag);
        OrderOutPut(back);
        printf("\n");
        return;
    } 
    while(front<rear)
    {
          
        if(!memcmp(Save[front].state,final,sizeof(final)))
        {
            OutPut(front);
            printf("\n");
            return;
        }    
        memcpy(cur,Save[front].state,sizeof(cur));
        if(!LWC(1,Save[rear].state,FORWARD))break;
        if(!RWC(2,Save[rear].state,FORWARD))break;
        if(!LWCC(3,Save[rear].state,FORWARD))break;
        if(!RWCC(4,Save[rear].state,FORWARD))break;
        if(flag>=0)
        {  
            OutPut(flag);
            OrderOutPut(back);
            printf("\n");
            return;
        } 
        front++;
    }
    printf("NO SOLUTION WAS FOUND IN 16 STEPS\n");
}        
int main()
{
    int puzzle;
    scanf("%d",&puzzle);
    int i,j,k;
    memset(backhead,0,sizeof(backhead));
    memset(backnext,0,sizeof(backnext));
    back=flag=-1; 
    BackBFS();
    for(i=0;i<puzzle;i++)
    {
        Initial();
        back=flag=-1;      
        for(j=0;j<24;j++)scanf("%d",&origin[j]);        
        if(memcmp(origin,final,sizeof(final))==0)
        {
            printf("PUZZLE ALREADY SOLVED\n");
        }
        else
        {         
            BFS();
        }
    }
    return 0;
}                


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值