一.题目链接:
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;
}