搜索水题。因为只有8个数,排列一共有40320种,直接bfs,判重就行了。
但是判重的时候直接用8进制表示的话要88的bool数组。这种操作太low了,于是我们可以用康托展开,降成8!。
康托展开其实就是一个简单的公式,很好意会。。。。
#include <iostream>
#include <cstdlib>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int fac[]={0,1,2,6,24,120,720,5040,40320,362880};
int rnk;
bool vis[50005];
struct Node{
int a[9],step,pre;
char c;
}a,q[50005];
int cantor(Node b) {
int ans=0;
for(int i=1;i<=8;i++) {
int cnt=0;
for(int j=i+1;j<=8;j++) {
if(b.a[j]<b.a[i]) cnt++;
}
ans+=(cnt*fac[8-i]);
}
return ans;
}
Node A(Node x) {
for(int i=1;i<=4;i++) swap(x.a[i],x.a[9-i]);
return x;
}
Node B(Node x) {
swap(x.a[1],x.a[4]),swap(x.a[8],x.a[5]);
swap(x.a[2],x.a[4]),swap(x.a[7],x.a[5]);
swap(x.a[3],x.a[4]),swap(x.a[5],x.a[6]);
return x;
}
Node C(Node x) {
swap(x.a[3],x.a[2]),swap(x.a[7],x.a[6]),swap(x.a[2],x.a[6]);
return x;
}
int h,t;
void print(Node x) {
if(!x.pre) return;
print(q[x.pre]); printf("%c",x.c);
}
void bfs() {
h++,t++;
for(int i=0;i<9;i++)q[1].a[i]=i;
while(h<=t) {
bool flag=1;
for(int i=1;i<=8;i++) if(q[h].a[i]!=a.a[i]) {flag=0;break;}
if(flag) {printf("%d
",q[h].step),print(q[h]);exit(0);}
Node tp;int kt;
tp=A(q[h]);kt=cantor(tp);
if(!vis[kt]){vis[kt]=1;q[++t]=tp;q[t].step++,q[t].pre=h;q[t].c='A';}
tp=B(q[h]);kt=cantor(tp);
if(!vis[kt]){vis[kt]=1;q[++t]=tp;q[t].step++;q[t].pre=h;q[t].c='B';}
tp=C(q[h]);kt=cantor(tp);
if(!vis[kt]){vis[kt]=1;q[++t]=tp;q[t].step++;q[t].pre=h;q[t].c='C';}
h++;
}
}
int main() {
for(int i=1;i<=8;i++) scanf("%d",&a.a[i]);
bfs();
}