状态数不是很多,直接 bfs
输出方案就记录 pre 状态即可
但是问题在于存状态
可行的一些方案是:哈希/map,康托展开
于是就学了一波康托展开
用康托展开的地方的地方感觉不会很多,毕竟要 n^2 算
大概意思就是给一个排列 hash
计算出来的就是这个排列在所有 n 的排列中的排名
计算方式就从这里看吧
不过代码实现略有不同
大体思路是差不多的
逆展开就是当前这一位上的数字的排名
从可用数字中选出这个排名的数,并把它从可用集合中删除
代码:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;
const int MAXN = 11, MAXSIZ = 5;
struct INFO{
int stt[MAXN], stp, ex;
}bgn;
int ans, top;
int pi[MAXN], out[MAXN], tmp[MAXN];
int stp[363000], pre[363000], stk[363000];
bool getans, vis[10];
queue<INFO> q;
inline void turnmid(int *stt) {
register int tmp = stt[4];
stt[4] = stt[6]; stt[6] = stt[5]; stt[5] = tmp;
return;
}
inline void turnroll(int *stt) {
register int tmp = stt[1];
stt[1] = stt[4]; stt[4] = stt[7]; stt[7] = stt[8];
stt[8] = stt[9]; stt[9] = stt[6]; stt[6] = stt[3];
stt[3] = stt[2]; stt[2] = tmp;
return;
}
inline int expnd(int *dst) {
register int res = 0, tmp = 0;
for(int i = 1; i <= 9; ++i) {
tmp = 0;
for(int j = i + 1; j <= 9; ++j) tmp += (dst[j] < dst[i]);
res += tmp * pi[9 - i];
}
return res;
}
inline void antiex(int ex) {
register int siz = 8, val = 0;
for(int i = 0; i < 9; ++i) tmp[i] = i;
for(int i = 1; i <= 9; ++i) {
val = (ex / pi[9 - i]);
ex %= pi[9 - i];
out[i] = tmp[val];
for(int j = val; j < siz; ++j) tmp[j] = tmp[j + 1];
--siz;
}
return;
}
inline void write(int ex) {
getans = true;
while(~ex) {
stk[++top] = ex;
//printf("ex = %d\n", ex);
ex = pre[ex];
}
while(top) {
antiex(stk[top--]);
for(int i = 1; i <= 9; ++i)
printf("%d%c", out[i], " \n"[i % 3 == 0]);
putchar('\n');
}
return;
}
inline void bfs() {
bgn.ex = expnd(bgn.stt);
bgn.stp = 0;
pre[bgn.ex] = -1;
stp[bgn.ex] = 0;
q.push(bgn);
INFO cur, d1, d2;
while(!q.empty()) {
cur = q.front(); q.pop();
//printf("now state : \n");
//for(int i = 1; i <= 9; ++i)
// printf("%d%c", cur.stt[i], " \n"[i % 3 == 0]);
++cur.stp;
d1 = cur;
d2 = cur;
turnroll(d1.stt);
turnmid(d2.stt);
d1.ex = expnd(d1.stt);
d2.ex = expnd(d2.stt);
if(stp[d1.ex] > d1.stp) {
stp[d1.ex] = d1.stp;
pre[d1.ex] = cur.ex;
q.push(d1);
}
if(stp[d2.ex] > d2.stp) {
stp[d2.ex] = d2.stp;
pre[d2.ex] = cur.ex;
q.push(d2);
}
if(d1.ex == ans) {
printf("%d\n", d1.stp);
write(d1.ex);
return;
}
if(d2.ex == ans) {
printf("%d\n", d2.stp);
write(d2.ex);
return;
}
}
return;
}
int main() {
memset(stp, 0x3f, sizeof(stp));
pi[0] = pi[1] = 1;
for(int i = 0 ;i < 363000; ++i) pre[i] = -1;
for(int i = 2; i <= 9; ++i)
pi[i] = pi[i - 1] * i;
for(int i = 1; i <= 9; ++i) bgn.stt[i] = i - 1;
ans = expnd(bgn.stt);
for(int i = 1; i <= 9; ++i)
scanf("%d", &bgn.stt[i]);
bfs();
if(!getans)
puts("UNSOLVABLE");
return 0;
}