知识点: bfs 打表, 康托展开
思路: 先预处理"X12345678",“1X2345678”,“12X345678”,“123X45678”,“1234X5678”,“12345X678”,
“123456X78”,“1234567X8”,"12345678X"等状态
每次将给定的s1映射为9个状态中的一个x1,将s2通过s1到x1的映射得到目标状态x2,再根据打表得到答案即可
使用康托展开为了压缩空间
#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 9, MAXN = 4e5;
int f[N + 1];
int d[4][2] = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}};
string ops = "dlru"; // 这里的顺序不能改变,因为答案要输出字典序最小的
int vis[N][MAXN];
int pre[N][MAXN];
struct Node {
int status[N]; // 当前的状态
int idx; // x的位置
int hash; // hash值
};
int cantor(int s[]) {
int res = 0;
for(int i = 0; i < N; i++) {
int sum = 0;
for(int j = i + 1; j < N; j++)
if(s[i] > s[j]) sum++;
res += sum * f[N - i - 1];
}
return res;
}
void bfs(int k) {
Node start, cur, temp;
for(int i = 0, v = 1; i < N; i++)
if(i == k) start.status[i] = 0;
else start.status[i] = v++;
start.idx = k;
start.hash = cantor(start.status);
queue<Node> q;
q.push(start);
vis[k][start.hash] = 1;
while(q.size()) {
cur = q.front();
q.pop();
int x = cur.idx / 3, y = cur.idx % 3;
for(int i = 0; i < 4; i++) {
int xx = x + d[i][0], yy = y + d[i][1];
if(xx < 0 || xx >= 3 || yy < 0 || yy >= 3) continue;
temp = cur;
swap(temp.status[temp.idx], temp.status[xx * 3 + yy]);
temp.hash = cantor(temp.status);
if(vis[k][temp.hash] == -1) {
temp.idx = xx * 3 + yy;
vis[k][temp.hash] = i;
pre[k][temp.hash] = cur.hash;
q.push(temp);
}
}
}
}
void init() {
f[0] = f[1] = 1;
for(int i = 2; i <= N; i++) f[i] = f[i - 1] * i;
memset(vis, -1, sizeof vis);
memset(pre, -1, sizeof pre);
for(int i = 0; i < N; i++) bfs(i);
}
int main() {
init();
freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
string s1, s2;
for(int i = 0; i < T; i++) {
cin >> s1 >> s2;
int x1[N], x2[N];
for(int i = 0, v = 1; i < N; i++) {
if(s1[i] == 'X') x1[i] = 0;
else x1[i] = v++;
}
for(int i = 0; i < N; i++) {
if(s2[i] == 'X') x2[i] = 0;
else {
for(int j = 0; j < N; j++)
if(s2[i] == s1[j])
x2[i] = x1[j];
}
}
int k = s1.find('X');
int hash = cantor(x2);
string res = "";
while(hash != -1) {
res += ops[vis[k][hash]];
hash = pre[k][hash];
}
printf("Case %d: %d\n", i + 1, res.size() - 1);
for(int i = res.size() - 2; i >= 0; i--) printf("%c", res[i]);
printf("\n");
}
return 0;
}