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;
}


 


 

posted @ 2013-08-05 20:07  pangbangb  阅读(319)  评论(0编辑  收藏  举报