算法竞赛入门经典:第七章 暴力求解法 7.18八数码问题之哈希去重

来源:互联网 发布:电子听诊器 分析软件 编辑:程序博客网 时间:2024/05/17 23:07
/*八数码问题之哈希去重:输入:2 6 4 1 3 7 0 5 88 1 5 7 3 6 4 0 2输出:31*//*关键:1 哈希:把结点变成整数,但不必是一一对应。设计一个哈希函数h(x),然后将任意结点x映射到某个给定的范围[0,M-1]的整数即可,其中M是程序员根据可用内存大小自选的。不同结点哈希值相同时,用链表组织哈希值相同的链表。2 iSum = 10 * iSum + s[i];//把9个数字组成九位数,妙哉3 return iSum % MAXHASHSIZE;//确保hash函数值不超过hash表的大小的非负整数这里除数尽量取大质数4 int h = hash(st[x]);//求第x个状态组对应的哈希值int u = iHead[h];//向获取每条链中的链首值while(u)//这个while的作用是遍历具有相同哈希值的一条链,如果能找到,说明插入失败,如果找不到,则采用头插法插入新来的节点{if(memcmp(st[u],st[x],sizeof(st[x])) == 0)//如果发现经过哈希值计算中的某个结点与源节点相同,说明之前已经有过该状态值,此时该状态相当于已访问{return false;}u = iNext[u];}iNext[x] = iHead[h];//采用头插法,获取头结点的指向iHead[h] = x;//将链中加入第x个状态编号*/#include <stdio.h>#include <string.h>#include <stdlib.h>const int MAXSIZE = 1000000;typedef int State[9];State st[MAXSIZE],stEnd;const int MAXHASHSIZE = 100003;int iHead[MAXHASHSIZE];int iNext[MAXSIZE];int iDist[MAXSIZE];int go[][2] = {{-1,0},{1,0},{0,-1},{0,1}};int hash(State& s){int iSum = 0;for(int i = 0 ; i < 9 ; i++){iSum = 10 * iSum + s[i];//把9个数字组成九位数,妙哉}return iSum % MAXHASHSIZE;//确保hash函数值不超过hash表的大小的非负整数这里除数尽量取大质数}bool isInsert(int x){int h = hash(st[x]);//求第x个状态组对应的哈希值int u = iHead[h];//向获取每条链中的链首值while(u)//这个while的作用是遍历具有相同哈希值的一条链,如果能找到,说明插入失败,如果找不到,则采用头插法插入新来的节点{if(memcmp(st[u],st[x],sizeof(st[x])) == 0)//如果发现经过哈希值计算中的某个结点与源节点相同,说明之前已经有过该状态值,此时该状态相当于已访问{return false;}u = iNext[u];}iNext[x] = iHead[h];//采用头插法,获取头结点的指向iHead[h] = x;//将链中加入第x个状态编号return true;}int bfs(){int iFront = 1,iRear = 2;memset(iHead,0,sizeof(iHead));while(iFront < iRear){State& state = st[iFront];if(memcmp(stEnd,state,sizeof(state)) == 0){return iFront;}int iX,iY,iZ;for(iZ = 0 ; iZ < 9 ; iZ++){if(!state[iZ]){break;}}iX = iZ / 3;iY = iZ % 3;int iNewZ,iNewX,iNewY;for(int i = 0 ; i < 4; i++){iNewX = go[i][0] + iX;iNewY = go[i][1] + iY;iNewZ = iNewX * 3 + iNewY;if(iNewX >= 0 && iNewX < 3 && iNewY >= 0 && iNewY < 3){State& newState = st[iRear];memcpy(&newState,&state,sizeof(state));newState[iNewZ] = state[iZ];newState[iZ] = state[iNewZ];iDist[iRear] = iDist[iFront] + 1;if(isInsert(iRear)){iRear++;}}}iFront++;}return -1;}void process(){iDist[1] = 0;for(int i = 0; i < 9; i++){scanf("%d",&st[1][i]);}for(int j = 0 ; j < 9 ; j++){scanf("%d",&stEnd[j]);}int iRes = bfs();if(iRes > 0){printf("%d\n",iDist[iRes]);}else{printf("-1\n");}}int main(int argc,char* argv[]){process();system("pause");return 0;}

0 0
原创粉丝点击