POJ1077八数码问题哈希,bfs

来源:互联网 发布:java入门123 编辑:程序博客网 时间:2024/05/15 11:09

八数码问题,这里的题意是将序列变为1,2,3,4,5,6,7,8,x的步骤,表示出x的变动,因为进行移动一定是x与某数的互换,所有总体上可以由x的移动来表示

u,d,l,r分别表示上下左右

 

利用哈希的方式构造结点查找表并且用以检查重复

#include"iostream"#include"cstring"#define EPT(m,n) for(int (m)=0;(m)<(n);(m)++)using namespace std;const int MAXSIZE = 567890;const int ESIZE = 9;typedef char State[ESIZE];State q[MAXSIZE];State t = {'1','2','3','4','5','6','7','8','x'};int head[MAXSIZE];int next[MAXSIZE];int proc[MAXSIZE];int last_step[MAXSIZE];int add_zero[MAXSIZE];char move[4] = {'r','l','d','u'};int d[4][2] ={{0,1},{0,-1},{1,0},{-1,0}};void init_lookup_table(){memset(head,0,sizeof(head));}int hash(State s){int v = 0;EPT(i,9){v = v * 10 + (s[i] - '0');}return v % MAXSIZE;}int try_to_insert(int s){int h = hash(q[s]);int u = head[h];    while(u){if(memcmp(q[u],q[s],sizeof(q[s])) == 0)return 0;u = next[u];            //下一个结点}next[s] = head[h];            //查找表头head[h] = s;return 1;}void print(int idx){if(last_step[idx] != 0)print(last_step[idx]);printf("%c",move[proc[idx]]);}int bfs(){init_lookup_table();int front = 0,rear = 1;int zero;EPT(e,9)if(q[0][e] == 'x'){zero = e;break;}add_zero[0] = zero;while(front < rear){State &u = q[front];if(memcmp(u,t,sizeof(t)) == 0){print(front);return 0;}            zero = add_zero[front];EPT(i,4){int x = (zero % 3) + d[i][1];int y = (zero / 3) + d[i][0];if(x > -1 && x < 3 && y > -1 && y < 3){       //判断移动是否合法int tem = y * 3 + x;State &v = q[rear];memcpy(v,u,sizeof(u));v[tem] = v[tem] ^ v[zero];v[zero] = v[tem] ^ v[zero];v[tem] = v[tem] ^ v[zero];if(try_to_insert(rear)){proc[rear] = i;add_zero[rear] = tem;last_step[rear] = front;rear ++;}}}front ++;}return 1;}int main(void){EPT(i,9){scanf("%c",q[0] + i);getchar();}if(bfs()){printf("unsolvable");}return 0;}


 

原创粉丝点击