這是個簡單題。一看就是用隊列來BFS,因為1-8八個數位全排列有8!=40320種。唯一需要解決的問題就是怎麼把8個數位每種不同的排列映射到唯一的整數上,因為如果用一個大小為[87654321]數組,浪費了大量的儲存空間,必定導致超記憶體。找到一個叫“康托展開”的東東,真是慚愧啊,很簡單的東西,其實自己應該都能想到才對。很簡單的思想:把每種排列映射為該排列在全排列中的次序即可。
/*ID: morgan_xwwLANG: CTASK: 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();}