LA 3618 Cubic Eight-Puzzle

         立体的八数码问题。

        普通的DFS和BFS就别想了,迭代加深TLE,而用启发式搜索又想不到合适的启发函数。可发现目标状态有固定的2^8种,而状态转移的方式最多只有4种......所以用双向bfs,应该能解决问题。因为会产生很多重复的状态,所以用hash表判断一下重复的状态。stl的hash会TLE,所以还是手写静态链表哦。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define hashMax    500009
#define tableMax 50000000
using namespace std;
int sta[4][4],tar[4][4],cta[4][4];
int roll_up[7]={0,3,6,1,5,4,2};
int roll_left[7]={0,5,4,6,2,1,3};
int roll_right[7]={0,5,4,6,2,1,3};
int roll_down[7]={0,3,6,1,5,4,2};
int convert(char c)
{
    if (c == 'W')
        return 1;
    if (c == 'R')
        return 3;
    if (c == 'B')
        return 5;
    return 8;
}
struct qNode
{
    int val;
    int step;
    qNode()
    {
    }
    qNode(int v,int s)
    {
        val=v;
        step=s;
    }
    ~qNode()
    {
    }
};
queue<qNode> fq;
queue<qNode> rq;
struct node
{
    int v;
    int next;
};
struct hashTable
{
    node hash[tableMax];
    int lh;
    void initHash()
    {
        int i;
        lh=hashMax;
        for (i=0; i<hashMax; i++)
            hash[i].v=-1;
    }
    bool insert(int v)
    {
        int tp;
        tp=v%hashMax;
        if (hash[tp].v == -1)
        {
            hash[tp].v=v;
            hash[tp].next=-1;
            return true;
        }
        while (hash[tp].next != -1)
        {
            tp=hash[tp].next;
        }
        hash[tp].next=lh;
        hash[lh].v=v;
        hash[lh].next=-1;
        lh++;
        return true;
    }
    bool find(int v)
    {
        int tp;
        tp=v%hashMax;
        if (hash[tp].v == v)
            return true;
        if (hash[tp].v == -1)
            return false;
        tp=hash[tp].next;
        while (tp != -1)
        {
            if (hash[tp].v == v)
                return true;
            tp=hash[tp].next;
        }
        return false;
    }
};
hashTable fhash,rhash;
int getHash(int gh[][4])
{
    int cnt,ite,i,j;
    ite=1;
    cnt=0;
    for (i=1; i<=3; i++)
    {
        for (j=1; j<=3; j++)
        {
            cnt+=gh[i][j]*ite;
            ite*=10;
        }
    }
    return cnt;
}
void dfs(int x,int y)
{
    if (y == 4)
    {
        dfs(x+1,1);
        return ;
    }
    if (x == 4)
    {
        x=getHash(cta);
        rhash.insert(x);
        rq.push(qNode(x,0));
        return ;
    }
    cta[x][y]=tar[x][y];
    dfs(x,y+1);
    cta[x][y]++;
    dfs(x,y+1);
}
struct Board
{
    int a[4][4];
    int x,y;
    void printOut()
    {
        int i,j;
        for (i=1; i<=3; i++)
        {
            for (j=1; j<=3; j++)
            {
                printf("%d ",a[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    int toNumber()
    {
        return getHash(a);
    }
    void toArray(int tx)
    {
        int i,j;
        for (i=1; i<=3; i++)
        {
            for (j=1; j<=3; j++)
            {
                a[i][j]=tx%10;
                if (a[i][j] == 8)
                {
                    x=i;
                    y=j;
                }
                tx/=10;
            }
        }
    }
    bool moveUp()
    {
        if (x == 3)
            return false;
        a[x][y]=roll_up[a[x+1][y]];
        a[x+1][y]=8;
        return true;
    }
    bool moveDown()
    {
        if (x == 1)
            return false;
        a[x][y]=roll_down[a[x-1][y]];
        a[x-1][y]=8;
        return true;
    }
    bool moveLeft()
    {
        if (y == 3)
            return false;
        a[x][y]=roll_left[a[x][y+1]];
        a[x][y+1]=8;
        return true;
    }
    bool moveRight()
    {
        if (y == 1)
            return false;
        a[x][y]=roll_right[a[x][y-1]];
        a[x][y-1]=8;
        return true;
    }
    bool move(int type)
    {
        switch(type)
        {
            case 0:
                return moveUp();
            case 1:
                return moveDown();
            case 2:
                return moveLeft();
            case 3:
                return moveRight();
        }
        return false;
    }
};
int bfs()
{
    Board b,tb;
    qNode qn,tqn;
    int cs,tf,tstep,i;
    cs=0;
    while (cs<30 && !fq.empty() && !rq.empty())
    {
       // printf("%d\n",cs);
        if (fq.size() > rq.size())
        {
            tstep=rq.front().step;
            while (rq.front().step == tstep)
            {
                qn=rq.front();
                b.toArray(qn.val);
                for (i=0; i<4; i++)
                {
                    tb=b;
                    if (tb.move(i) == true)
                    {
                        tqn.step=qn.step+1;
                        tqn.val=tb.toNumber();
                        if (fhash.find(tqn.val) == true)
                            return cs+1;
                        if (rhash.find(tqn.val) == false)
                        {
                            rhash.insert(tqn.val);
                            rq.push(tqn);
                        }
                    }
                }
                rq.pop();
            }
        }
        else
        {
            tstep=fq.front().step;
            while (fq.front().step == tstep)
            {
                qn=fq.front();
                b.toArray(qn.val);
            //    printf("val=%d\n",qn.val);
                for (i=0; i<4; i++)
                {
               //     printf("i=%d\n",i);
                    tb=b;
                    if (tb.move(i) == true)
                    {
                        tqn.step=qn.step+1;
                        tqn.val=tb.toNumber();
                   //     tb.printOut();
                        if (rhash.find(tqn.val) == true)
                            return cs+1;
                        if (fhash.find(tqn.val) == false)
                        {
                            fq.push(tqn);
                            fhash.insert(tqn.val);
                      //      printf("tqn.val=%d\n",tqn.val);
                        }
                    }
                }
                fq.pop();
            }
        }
        cs++;
    }
    return -1;
}
int main()
{
    int n,m,i,j;
    char c;
    while (true)
    {
        scanf("%d%d",&n,&m);
        if (n == 0 || m == 0)
            break;
        i=n;
        n=m;
        m=i;
        rhash.initHash();
        fhash.initHash();
        while (!rq.empty()) rq.pop();
        while (!fq.empty()) fq.pop();
        for (i=1; i<=3; i++)
        {
            for (j=1; j<=3; )
            {
                c=getchar();
                if (c >= 'A' && c <= 'Z')
                {
                    tar[i][j]=convert(c);
                    sta[i][j]=1;
                    j++;
                }
            }
        }
        sta[n][m]=8;
        i=getHash(sta);
        dfs(1,1);
        if (rhash.find(i) == true)
        {
            printf("0\n");
            continue;
        }
        fhash.insert(i);
        fq.push(qNode(i,0));
        printf("%d\n",bfs());
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值