poj 3131 Cubic Eight-Puzzle 双向广搜 Hash判重
挺不错的题目,很锻炼代码能力和调试能力~
题意:初始格子状态固定,给你移动后格子的状态,问最少需要多少步能到达,如果步数大于30,输出-1。
由于单向搜索状态太多,搜到二十几就会爆了,所以应该想到双向广搜。
对于每一个格子,我只需要记录上面和前面的格子颜色,因为格子左右移动前面颜色不变上面颜色变了,前后移动的话只是前面和上面的颜色交换了而已,不过写的太挫了。。。应该直接进制压缩一下。。。我还用了两个数来表示前面和上面的颜色,下次把这些搜索题全A了后再回来重新写一下,重写效果也会不错,并不是题目a了这题就好了。
#include <stdio.h> #include <string.h> #define LL __int64 const int mod = 100007; struct HASH{ int head[mod+10], E, next[222222]; int v1[222222], v2[222222], c[222222]; void init() { memset(head, -1, sizeof(head)); E = 0; } int gethash(int x,int y) { return (((LL)x + y)%mod+mod)%mod; } int isin(int x, int y) { int u = gethash(x, y); for(int i = head[u];i != -1;i = next[i]) { if(v1[i] == x && v2[i] == y) return c[i]; } return -1; } void push(int x, int y, int step) { int u = gethash(x, y); v1[E] = x; v2[E] = y; c[E] = step; next[E] = head[u]; head[u] = E++; } }ha1, ha2; struct PP{ int st1, st2; int step; PP(){} PP(int st1, int st2, int step) : st1(st1), st2(st2), step(step) {} }cur, to, q[1000002]; int dx[] = {1, -1, 0, 0}; int dy[] = {0, 0, 1, -1}; int a[22], b[22], d[2222]; void swap(int &a, int &b) { int t = a; a = b; b = t; } void get_zt(int st1, int st2) { for(int i = 9;i >= 1;i --) a[i] = st1%10, st1 /= 10; for(int i = 9;i >= 1;i --) b[i] = st2%10, st2 /= 10; } void get_xy(int &st1, int &st2) { st1 = st2 = 0; for(int i = 1;i <= 9; i++) st1 = st1*10+a[i]; for(int i = 1;i <= 9; i++) st2 = st2*10+b[i]; } bool judge(int go) { int ret = 0; for(int i = 1;i <= 9; i++) ret = ret*10+a[i]; return go == ret; } int getnew(int a, int b) { int vis[5], i; for(i = 1;i <= 3; i++) vis[i] = 0; vis[a]++;vis[b]++; for(i = 1;i <= 3; i++) if(!vis[i]) return i; } int min(int a, int b) { return a>b?b:a; } int bfs(int st1,int st2, int go) { ha1.init(); ha1.push(st1, st2, 0); int head = 0, tail = 0; q[tail++] = PP(st1, st2, 0); int i, j, k; while(head < tail) { cur = q[head++]; st1 = cur.st1, st2 = cur.st2; get_zt(st1, st2); int now ; for(i = 1;i <= 9; i++) if(a[i] == 4) { now = i; break; } int x = now/3+1, y = now%3; if(y == 0) y = 3, x--; for(i = 0;i < 4; i++) { int xx = x+dx[i]; int yy = y+dy[i]; if(xx < 1 || xx > 3 || yy < 1 || yy > 3) continue; int then = (xx-1)*3+yy; swap(a[now], a[then]);swap(b[now], b[then]); if(i < 2) { swap(a[now], b[now]); if(judge(go)) { return cur.step+1; } get_xy(to.st1, to.st2); to.step = cur.step+1; if(ha1.isin(to.st1, to.st2) == -1 && to.step <= 20) { ha1.push(to.st1, to.st2, to.step); if(to.step > 20) continue; q[tail++] = to; } swap(a[now], b[now]); } else { a[now] = getnew(a[now], b[now]); if(judge(go)) { return cur.step+1; } get_xy(to.st1, to.st2); to.step = cur.step+1; if(ha1.isin(to.st1, to.st2) == -1 && to.step <= 20) { ha1.push(to.st1, to.st2, to.step); if(to.step > 20) continue; q[tail++] = to; } a[now] = getnew(a[now], b[now]); } swap(a[now], a[then]);swap(b[now], b[then]); } } int temp , tot = 0; int N = 1<<8; for(i = 0;i < N; i++) { temp = go; for(j = 9;j >= 1; j--) a[j] = temp%10 , temp /= 10; int id1 = 1, id2 = 0, sum = 0; while(id1 <= 9) { if(a[id1] == 4) { sum = sum*10+4; id1++; continue; } if((1<<id2) & i) { for(k = 3;k >= 1; k--) if(k != a[id1]) break; sum = sum*10+k; } else { for(k = 1;k <= 3; k++) if(k != a[id1]) break; sum = sum*10+k; } id1++, id2++; } d[tot++] = sum; } for(i = 0;i < tot; i++){ int now = ha1.isin(go, d[i]); if(now >= 0) return now; } int ans = 1111111; for(int ii = 0;ii < tot;ii++) { ha2.init(); cur = PP(go, d[ii], 0); int head = 0, tail = 0; q[tail++] = cur; int ok = 0; while(head < tail) { cur = q[head++]; st1 = cur.st1, st2 = cur.st2; get_zt(st1, st2); int now ; for(i = 1;i <= 9; i++) if(a[i] == 4) { now = i; break; } int x = now/3+1, y = now%3; if(y == 0) y = 3, x--; for(i = 0;i < 4; i++) { int xx = x+dx[i]; int yy = y+dy[i]; if(xx < 1 || xx > 3 || yy < 1 || yy > 3) continue; int then = (xx-1)*3+yy; swap(a[now], a[then]);swap(b[now], b[then]); if(i < 2) { swap(a[now], b[now]); get_xy(to.st1, to.st2); to.step = cur.step+1; int temp = ha1.isin(to.st1, to.st2); if(temp >= 0) { ok = 1; ans = min(ans, temp+to.step);continue; } if(ha2.isin(to.st1, to.st2) == -1 && to.step <= 10) { ha2.push(to.st1, to.st2, to.step); q[tail++] = to; } swap(a[now], b[now]); } else { a[now] = getnew(a[now], b[now]); get_xy(to.st1, to.st2); to.step = cur.step+1; int temp = ha1.isin(to.st1, to.st2); if(temp >= 0) { ok = 1; ans = min(ans, temp+to.step);continue; } if(ha2.isin(to.st1, to.st2) == -1 && to.step <= 10) { ha2.push(to.st1, to.st2, to.step); q[tail++] = to; } a[now] = getnew(a[now], b[now]); } swap(a[now], a[then]);swap(b[now], b[then]); if(ok) break; } if(ok) break; } } if(ans > 30) return -1; return ans; } int main() { int i, x, n, m; while(scanf("%d%d", &m, &n) != -1 && n) { int go = 0, st1 = 0, st2 = 0; char ch[2]; for(i = 1;i <= 9; i++) { scanf("%s", ch); if(ch[0] == 'W') x = 1; else if(ch[0] == 'R') x = 2; else if(ch[0] == 'B') x = 3; else x = 4; go = go*10 + x; if(i == (n-1)*3 + m) { st1 = st1*10+4; st2 = st2*10+4; } else { st1 = st1*10+1; st2 = st2*10+2; } } if(st1 == go) { puts("0"); continue; } printf("%d\n", bfs(st1, st2, go)); } return 0; }