这是个简单题。一看就是用队列来BFS,因为1-8八个数字的全排列有8!=40320种。唯一需要解决的问题就是怎么把8个数字的每种不同的排列映射到唯一的整数上,因为如果用一个大小为[87654321]数组,浪费了大量的存储空间,必定导致超内存。找到一个叫“康托展开”的东东,真是惭愧啊,很简单的东西,其实自己应该都能想到才对。很简单的思想:把每种排列映射为该排列在全排列中的次序即可。
/*
ID: morgan_xww
LANG: C
TASK: msquare
*/
#include <stdio.h>
#include <string.h>
struct
{
int vlu;
int cnt;
int pre;
char tsf;
} Q[50000];
int fac[9] = {1,1,2,6,24,120,720,5040,40320};
int Target, Qnum, p;
char vst[50000];
int KT(int s[]) //康托展开
{
int i, j, t, sum;
sum = 0;
for (i=0; i<8; i++)
{
t = 0;
for (j=i+1; j<8; j++)
if (s[j] < s[i])
t++;
sum += t*fac[7-i];
}
return sum+1;
}
void invKT(int n, int s[]) //康托展开的逆运算
{
int i, j, t, vst[8]={0};
n--;
for (i=0; i<8; i++)
{
t = n/fac[7-i];
for (j=1; j<=8; j++)
if (!vst[j])
{
if (t == 0) break;
t--;
}
s[i] = j;
vst[j] = 1;
n %= fac[7-i];
}
}
void PrintAns()
{
int i, k;
char ans[50000];
k = Qnum-1;
printf("%d", Q[k].cnt);
i = 0;
while (Q[k].cnt)
{
ans[i++] = Q[k].tsf;
k = Q[k].pre;
}
k = 0;
while (--i >= 0)
{
if (k%60 == 0)
printf("/n");
printf("%c", ans[i]);
k++;
}
printf("/n");
exit(0);
}
void AddQue(int k, char ch) //加入队列
{
if (!vst[k])
{
Q[Qnum].vlu = k;
Q[Qnum].cnt = Q[p].cnt+1;
Q[Qnum].pre = p;
Q[Qnum].tsf = ch;
Qnum++;
vst[k] = 1;
}
if (k == Target)
PrintAns();
}
void Transf(int s[]) //三种变换
{
int i, t[8];
// A变换
for (i=0; i<8; i++) t[i] = s[7-i];
AddQue(KT(t), 'A');
// B变换
t[0] = s[3];
t[7] = s[4];
for (i=1; i<=3; i++) t[i] = s[i-1];
for (i=4; i<=6; i++) t[i] = s[i+1];
AddQue(KT(t), 'B');
// C变换
t[0] = s[1];
s[1] = s[6];
s[6] = s[5];
s[5] = s[2];
s[2] = t[0];
AddQue(KT(s), 'C');
}
void BFS()
{
int s[8];
p = 0;
while (p < Qnum)
{
invKT(Q[p].vlu, s);
Transf(s);
p++;
}
}
int main()
{
//freopen("msquare.in", "r", stdin);
//freopen("msquare.out", "w", stdout);
int i, t;
int stat[8]={1,2,3,4,5,6,7,8};
int targ[8];
for (i=0; i<8; i++)
scanf("%d", &targ[i]);
Target = KT(targ);
t = KT(stat);
if (t == Target)
{
printf("0/n/n");
exit(0);
}
Q[0].vlu = t;
Q[0].cnt = 0;
Qnum = 1;
vst[t] = 1;
BFS();
}