八数码

我的天!!这道题看刘汝佳的书首先就看不懂,之后上网找解题报告也看不懂,主要是以为哈希技术不知道

后来问了一下凯哥根据自己的理解勉强AC出来了

哈希技术 简略点就是将 用一个哈希函数将一个很大的数据分成好几份,并且每组数据利用链接进行遍历

哈希函数的构造一般用一个很大的素数

int hash(int ss[9]){
    int sum=0;
    for(int i=0;i<9;i++)
    sum=sum*10+ss[i];
    return sum%MAX_SIZE;
}
bool Try_to_insert(int s){
    int h=hash(State[s]);
    int u=head[h];
    while(u){
         if(memcmp(State[u],State[s],sizeof(State[s]))==0)
         return false;
         u=next[u];
    }
    next[s]=head[h];
    head[h]=s;
    return true;
}
head[h]就代表所有经过哈希函数求解之后得到的值为h的数的集合的链节头
next[s]为s的下一个元素是什么
我的天总之这题做的水的很,还有很多搞不懂的地方
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXD 5
#define MAX_SIZE 1000003
const int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
const char dirs[]="UDLR";/*上、右、下、左*/
int State[MAX_SIZE][9];
char Str[MAX_SIZE][100];
int dist[MAX_SIZE];
int head[MAX_SIZE];
int next[MAX_SIZE];
int front;
int back;
int hash(int ss[9]){
    int sum=0;
    for(int i=0;i<9;i++)
    sum=sum*10+ss[i];
    return sum%MAX_SIZE;
}
bool Try_to_insert(int s){
    int h=hash(State[s]);
    int u=head[h];
    while(u){
         if(memcmp(State[u],State[s],sizeof(State[s]))==0)
         return false;
         u=next[u];
    }
    next[s]=head[h];
    head[h]=s;
    return true;
}
void display(int mat[][4]){
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++)
            printf("%d ",mat[i][j]);
        printf("\n");
    }
}
void solve(){
    front = 1;
    back  = 2;
    while(front<back){
        int temp[4][4];
        int x,y;
        for(int i=0,k=0;i<3;i++)
            for(int j=0;j<3;j++,k++){
                temp[i][j]=State[front][k];
                if(temp[i][j]==0){
                    x=i;y=j;/*记录为0的点*/
                }
            }
        /*先转化为2维数组*/
        for(int i=0;i<4;i++){
            int st[4][4];
            int nx=x+dir[i][0];
            int ny=y+dir[i][1];
            memcpy(st,temp,sizeof(st));
            if(nx>=0&&ny>=0&&nx<3&&ny<3){
                st[x][y] = st[nx][ny];
                st[nx][ny] = 0;
                /*交换块的位置*/
                for(int z=0,k=0;z<3;z++)
                    for(int j=0;j<3;j++,k++)
                    State[back][k]=st[z][j];
                int z;
                for(z=0;z<strlen(Str[front]);z++){
                    Str[back][z]=Str[front][z];
                }
                Str[back][z]=dirs[i];
                Str[back][z+1]='\0';
                if(Try_to_insert(back))
                   back++;
            }
        }
        front++;
    }
}
int main(){
    int N;
    scanf("%d",&N);
    for(int cases=1;cases<=N;cases++){
            memset(head,0,sizeof(head));
            memset(next,0,sizeof(next));
            memset(dist,0,sizeof(dist));
            memset(State,0,sizeof(State));
            memset(Str,0,sizeof(Str));
            for(int i=0;i<9;i++)
            scanf("%d",&State[1][i]);
            Str[1][0]='\0';
            solve();
            printf("Puzzle #%d\n",cases);
            for(int i=0;i<9;i++){
                printf("%d",State[back-1][i]);
                if((i+1)%3==0)
                printf("\n");
                else
                printf(" ");
            }
            puts(Str[back-1]);
            printf("\n");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值