uva704 - Colour Hash

链接:Miku

------------------------

思路简单,双向bfs,实现困难

---------------------------

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100003;
int f,ans1,ans2,head[maxn],nex[maxn],fr[maxn],mov[maxn],step[maxn];
int ansi[maxn][25],si[maxn][25],now[25],goal[24]={0,3,4,3,0,5,6,5,0,1,2,1,0,7,8,7,0,9,10,9,0};
int anhead[maxn],annex[maxn],anfr[maxn],anmov[maxn];
int t;
int check(){
    for(int i=0;i<=20;++i) 
        if(now[i]!=goal[i]) 
            return 0;
    return 1;
}
int cmp(int *a,int *b){
    for(int i=0;i<=20;++i)
        if(a[i]!=b[i])
            return 0;
    return 1;
}
int hashh(int x){
    int s=0;
    for(int i=1;i<=20;++i){
        s=(s*11+si[x][i])%maxn;
    }
    return s;
}
int check2(int x){
    int h=hashh(x);
    int u=anhead[h];
    while(u){
        if(cmp(ansi[u],si[x])){
            ans2=u;
            return 1;
        }
        u=annex[u];
    }
    return 0;
}
int add(int x){//x状态的所有拓展状态 
    int h=hashh(x);
    int u=head[h];
    while(u){
        if(cmp(si[u],si[x])){
            return 0;
        }
        u=nex[u];
    }
    nex[x]=head[h];//链表 
    head[h]=x;
    return 1;
}
void bfs(int *x,int now){
    int tail=0,front=1;
    step[0]=0;
    for(int i=0;i<=20;++i) si[0][i]=x[i];
    memset(head,0,sizeof(head));
    memset(nex,0,sizeof(nex));
    add(0);
    while(tail<front){
        if(now&&check2(tail)){
            f=1;
            ans1=tail;
            break;
        }
        if(step[tail]>8)
        break;
        for(int i=0;i<=9;++i)
        si[front][i+2]=si[tail][i];
        si[front][0]=si[tail][10];
        si[front][1]=si[tail][11];
        for(int i=12;i<=20;++i) 
        si[front][i]=si[tail][i];
        if(add(front)){
            step[front]=step[tail]+1;
            mov[front]=1;
            fr[front]=tail;
            front++;
        }
        for(int i=9;i<=18;++i)
        si[front][i]=si[tail][i+2];
        si[front][19]=si[tail][9];
        si[front][20]=si[tail][10];
        for(int i=0;i<=8;++i) 
        si[front][i]=si[tail][i];
        if(add(front)){
            step[front]=step[tail]+1;
            mov[front]=2;
            fr[front]=tail;
            front++;
        }
        for(int i=0;i<=9;++i)
        si[front][i]=si[tail][i+2];
        si[front][10]=si[tail][0];
        si[front][11]=si[tail][1];
        for(int i=12;i<=20;++i) 
        si[front][i]=si[tail][i];
        if(add(front)){
            step[front]=step[tail]+1;
            mov[front]=3;
            fr[front]=tail;
            front++;
        }
        for(int i=9;i<=18;++i)
        si[front][i+2]=si[tail][i];
        si[front][9]=si[tail][19];
        si[front][10]=si[tail][20];
        for(int i=0;i<=8;++i) 
        si[front][i]=si[tail][i];
        if(add(front)){
            step[front]=step[tail]+1;
            mov[front]=4;
            fr[front]=tail;
            front++;
        }
        tail++;
    }
}
void printmov(int x){
    if(x){
        printmov(fr[x]);
        printf("%d",mov[x]);
    }
}
void anprint(int x){
    if(x){
        if(anmov[x]==2)
        printf("4");
        else
        printf("%d",(anmov[x]+2)%4);
        anprint(anfr[x]);
    }
}
int main(){
    scanf("%d",&t);
    bfs(goal,0);
    memcpy(anhead,head,sizeof(head));//an==从答案 
    memcpy(annex,nex,sizeof(nex));
    memcpy(anfr,fr,sizeof(fr));
    memcpy(anmov,mov,sizeof(mov));
    memcpy(ansi,si,sizeof(si));
    for(int i=1;i<=t;++i){
        for(int j=0;j<=23;++j)
        scanf("%d",&now[j]);
            if(check()){
                cout<<"PUZZLE ALREADY SOLVED\n";
                continue;
            }
            ans1=ans2=0;//答案坐标 
            f=0;
            bfs(now,1);
            if(f){
                printmov(ans1);
                anprint(ans2);
                cout<<endl;
            }else{
                cout<<"NO SOLUTION WAS FOUND IN 16 STEPS\n";
            }
    }
}

 

posted @ 2020-07-31 18:36  Simex  阅读(128)  评论(0编辑  收藏  举报