HDU1043_八数码问题


#include<iostream>
#include<string>
#include<queue>
using namespace std;
//通过康托展开来hash
//9!有362880
const int maxn = 400000;
int Step[maxn];
int P[maxn][2];//用于记录与前面一个的相对路径
int D[10];//用来统计0到9的阶乘
int si;
int ei;
//从答案向前寻找,统计所有的Step,后面用于查询

int toInt(int A[3][3])//康拓展开
{
    int t = 0;
    for (int i = 0; i<9; i++)
    {
        int x = A[i / 3][i % 3];
        //寻找后面比x小的数字
        int cnt = 0;
        for (int j = i + 1; j < 9; j++)
        {
            if (A[j / 3][j % 3] < x) cnt++;
        }
        t += (cnt)*D[8 - i];
    }
    return t+1;
}

typedef struct node
{
    int A[3][3];
    int step;
    int id;
    int loc;
    node(int B[3][3], int ste, int _id, int _loc)
    {
        for (int i = 0; i<9; i++)
        {
            A[i / 3][i % 3] = B[i / 3][i % 3];
        }
        step = ste;
        id = _id;
        loc = _loc;
    }
}node;
queue<node> Sta;
int Op[4][2] = { 0,1,0,-1,1,0,-1,0 };

int main()
{
    int E[3][3];
    int S[3][3];
    memset(P, -1, sizeof(P));
    memset(Step, -1, sizeof(Step));
    D[0] = 1;
    for (int i = 1; i<10; i++)
    {
        D[i] = D[i - 1] * i;
    }
    int x;
    for (int i = 0; i < 9; i++)
    {
        E[i / 3][i % 3] = i + 1;
    }
    ei = toInt(E);
    node firnode(E, 0,ei,8);
    Sta.push(firnode);
    Step[ei] = 0;
    while (!Sta.empty())
    {
        node tn = Sta.front();
        Sta.pop();
        //有四种移动情况
        int t = tn.loc;
        int x = (t) / 3;
        int y = t % 3;
        for (int i = 0; i < 4; i++)
        {
            int nx = x + Op[i][0];
            int ny = y + Op[i][1];
            if (nx >= 0 && nx < 3 && ny >= 0 && ny < 3)
            {
                node nn = tn;
                int nloc = 3 * nx + ny;
                nn.A[x][y] = nn.A[nx][ny];
                nn.A[nx][ny] = 9;
                int ni = toInt(nn.A);
                if (Step[ni] == -1)
                {
                    nn.loc = nloc;
                    nn.step = tn.step + 1;
                    nn.id = ni;
                    Step[ni] = tn.step+1;
                    P[ni][0] = tn.id;
                    P[ni][1] = i;
                    Sta.push(nn);
                }
            }
        }
    }
    string s;
    ios::sync_with_stdio(false);
    while (cin >> s)
    {
        if (s[0] == 'x')
            S[0][0] = 9;
        else
            S[0][0] = s[0] - '0';
        for (int i = 1; i < 9; i++)
        {
            cin >> s;
            if (s[0] == 'x')
            {
                s[0] = '9';
            }
            S[i / 3][i % 3] = s[0] - '0';
        }

        si = toInt(S);
        if (Step[si] == -1)
        {
            cout << "unsolvable" << endl;
        }
        else
        {
            int p = si;
            //cout << Step[si] << endl;
            while (P[p][0] != -1)//说明有上一个节点
            {
                if (P[p][1] == 0)
                {
                    cout << "l";
                }
                else if (P[p][1] == 1)
                {
                    cout << "r";
                }
                else if (P[p][1] == 2)
                {
                    cout << "u";
                }
                else
                {
                    cout << "d";
                }
                p = P[p][0];
            }
            cout << endl;
        }
    }

    return 0;
}

992

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值