一.题目链接:

HDU-3567

二.题目大意:

Eight 的升级版,游戏规则相同.

每次给出两个字符串 A, B,问 从 A 到 B 的最少步数 并 打印最小字典序的路径.

三.分析:

看了大神的分析才懂。。。

在这里阐述一下.

只考虑 X 的位置,由于 1 ~ 8 数字无特殊性

所以可将所给的 A 重新编号.

例如 A1:8 7 X 6 5 4 3  2 1

编号为 A2:1 2 X 3 4 5 6 7 8 

并使用相同的编号规则 给字符串 B 重新编号

这样 A2 -> B2 就等价与 A1-> B1.

又因为 X 的位置只有 9 种情况,所以可以先用 BFS 打表

之后重新编号 + 查询即可.

四.代码实现:

#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;

const int M = (int)5e5;

struct node
{
    int D[9];
    int x;
    int y;
};

bool vis[M + 5];
int fa[9][M + 5];
int inflection[9];
char dir[9][M + 5];

int Move[4][2] = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}};

int cantor(struct node p)
{
    int sum = 0;
    int fac = 40320;
    for(int i = 0; i < 9; ++i)
    {
        int cnt = 0;
        for(int j = i + 1; j < 9; ++j)
        {
            if(p.D[j] < p.D[i])
                cnt++;
        }
        sum += fac * cnt;
        if(i == 8)
            return sum;
        fac /= 8 - i;
    }
}

void bfs(struct node p, int op)
{
    memset(vis, 0, sizeof(vis));
    struct node t;
    queue <node> q;
    int can1 = cantor(p);
    int can2;
    vis[can1] = 1;
    q.push(p);
    while(!q.empty())
    {
        p = q.front();
        q.pop();
        can1 = cantor(p);
        for(int i = 0; i < 4; ++i)
        {
            t = p;
            t.x += Move[i][0];
            t.y += Move[i][1];
            if(t.x < 0 || t.x >= 3 || t.y < 0 || t.y >= 3)
                continue;
            int pos = t.x * 3 + t.y;
            if(i == 0)
            {
                swap(t.D[pos], t.D[pos - 3]);
                can2 = cantor(t);
                if(!vis[can2])
                {
                    vis[can2] = 1;
                    dir[op][can2] = 'd';
                    fa[op][can2] = can1;
                    q.push(t);
                }
            }
            else if(i == 1)
            {
                swap(t.D[pos], t.D[pos + 1]);
                can2 = cantor(t);
                if(!vis[can2])
                {
                    vis[can2] = 1;
                    dir[op][can2] = 'l';
                    fa[op][can2] = can1;
                    q.push(t);
                }
            }
            else if(i == 2)
            {
                swap(t.D[pos], t.D[pos - 1]);
                can2 = cantor(t);
                if(!vis[can2])
                {
                    vis[can2] = 1;
                    dir[op][can2] = 'r';
                    fa[op][can2] = can1;
                    q.push(t);
                }
            }
            else if(i == 3)
            {
                swap(t.D[pos], t.D[pos + 3]);
                can2 = cantor(t);
                if(!vis[can2])
                {
                    vis[can2] = 1;
                    dir[op][can2] = 'u';
                    fa[op][can2] = can1;
                    q.push(t);
                }
            }
        }
    }
}

void init()
{
    struct node p, t;
    for(int i = 0; i < 9; ++i)
        p.D[i] = i + 1;
    for(int i = 0; i < 9; ++i)
    {
        t = p;
        t.D[i] = 0;
        t.x = i / 3;
        t.y = i % 3;
        bfs(t, i);
    }
}

 int read(struct node &p)
{
    int op;
    char ch;
    int pos = 0;
    while((ch = getchar()) != '\n')
    {
        if(ch == 'X')
        {
            op = pos;
            p.D[pos++] = 0;
        }
        else if(ch >= '1' && ch <= '8')
            p.D[pos++] = ch - '0';
    }
    return op;
}

int main()
{
    init();
    int T;
    scanf("%d", &T);
    getchar();
    for(int ca = 1; ca <= T; ++ca)
    {
        struct node p1, p2;
        int op = read(p1);
        read(p2);
        for(int i = 0; i < 9; ++i)
        {
            if(!p1.D[i])
                continue;
            inflection[p1.D[i]] = i + 1;
            p1.D[i] = i + 1;
        }
        for(int i = 0; i < 9; ++i)
        {
            if(!p2.D[i])
                continue;
            p2.D[i] = inflection[p2.D[i]];
        }
        int can1 = cantor(p1);
        int can2 = cantor(p2);
        stack <char> st;
        while(can1 != can2)
        {
            st.push(dir[op][can2]);
            can2 = fa[op][can2];
        }
        printf("Case %d: %d\n", ca, st.size());
        while(!st.empty())
        {
            printf("%c", st.top());
            st.pop();
        }
        printf("\n");
    }
    return 0;
}