通过C++写CFOP来解决三阶魔方和五阶魔方的基本理念(重置)
furry_zz
2025年06月20日 23:52

目标:通过c++写出一个程序来读取一颗五阶魔方的打乱状态,并输出该魔方的解法

使用方法:竖棱84法、CFOP

先来讨论三阶部分的解法

存储

存储方面,UP采用三种存储方式。第一种是简单存储魔方的六个面,维护六个二维数组(Up,Down,Front,Back,Left,Right),数组中的每个元素都是一个char类型的变量(U,D,F,B,L,R),数组的方向如下图所示

第二种是对于角块和棱块的存储,每个元素都是一个string类型的变量,例如DFL=“UBR”表示“在DFL这个角块的位置上是UBR角块”,FL=“BR”表示“在FL这个棱块的位置上是BR角块”,并且为了程序便于操作,我对色块设定了优先级,优先级高的排在前面,UD最高,FB其次,LR最低,这样就保证了棱角表示的唯一性。第三种就是对于CROSS所需的四棱的位置存储,类型是map<char,string>,char关键字表示该棱除‘D’外的另一个颜色,string就是‘D’在第一种存储中的位置,例如Position_Cross['L']="U12"表示“DL这个棱块的‘D’在Up[1][2]的位置”,第二种方法只是有助于理解,并没有实际用途!!

至此,存储问题解决了,对于每次转动也很好操作,通过模拟法就可以对魔方进行UDFBLRxyzMESudfblr及其反转(U')及其二次转动(U2),在转体之后,对魔方进行遍历,例如y'之后,L变成F等等。

CROSS---------------降群法、hash、BFS

这篇重置文章与前一版最大的不同就是修改了cross的算法。

准备工作:预先准备好由复原状态四步打乱而成的公式本,具体做法是再构建一个三阶魔方,从复原状态开始打乱1~4步,用map记下打乱后的状态,并逆序推出该打乱的复原公式,这样在复原时最多只用穷举前四步,后面的调用公式即可。

对cross情况的hash:存储棱块中非D色块的位置,以“LFRB”的顺序存储,例如cross的复原状态是“L32F32R32B32”。

cross所需棱块的状态更新方式:每种旋转都有各自的编码,将操作编成5位十进制编码,就可以实现O(5)时间复杂度的状态更新,字母编码方式为ASCII码减64再除以3,B'用BI表示,这样得到的字母编码是唯一的。例如:hash[7217]="U23",hash[71272]="U32"。

最后,是对bfs里的优化,打多个if过于冗长,用map和指针代替。

F2L与OLL

F2L会多一步把棱和角从其他槽中取出的过程,多打几个if就好了,然后就是AUF,把DFR棱块控到DFR或UFR的位置,最后对DFR中的D与FR中的F进行hash。如D→Up[3][3],F→Front[2][3],则该情况名为“U33F23”,并在公式本中选取公式操作,完成后转体。

OLL同理,对情况进行hash,方法很多,在此就不过多赘述了。

PLL

PLL是对顶层侧边的hash,UP的做法是将Left[1][1]处的色块定义为1,以L→F→R→B→L的循环依次递增,再以“L-F-R-B”的顺序对顶层色块翻译出的数字进行12位编码,再在公式本中选取公式操作,完成后AUF,三阶部分结束。

竖棱84法

1、合并中心

合并中心有2×2+1个公式本,黄白两面有两个,转体后四面中的两面有两个,后二心有一个。

调取公式本时,对整颗魔方进行遍历,将所需的块的位置记下,存到队列里。使用时,从队首取出相应数量的块,并进行18个分支的bfs,直到匹配到正确位置时调用公式。

18个分支:4Uw,L,R,F,B,U及反转和180°转动

在bfs的for循环里,可以通过再加关键字来节省时间,例如,在拼3、4面中心块时禁用L、R、4Rw函数。

2、合并棱块

前8棱

按照三阶棱块编码方式查找要合并的三个棱块,while(1)循环,退出循环的依据为L、R的棱块全部还原好,否则继续循环,该判断放在while循环内第一行。

合并UF棱块,以UF中棱为准,在其他棱块中寻找UF翼棱的位置。

以U(5,2)-F(1,2)棱的F(1,2)所在位置为第一关键字,以U(5,4)-F(1,4)棱的U(5,4)所在位置为第二关键字,共同组成一种前八棱的情况,调用第六公式集合并UF棱块。

后四棱

第一棱:取出BD棱块,并将UB、UF、DF三棱共同含有的棱块的中棱转到UF位置,套用第六公式集解决。

第二棱:在操作完第一棱后,剩余的棱块恰好在UB、UF、DF三位置,这样就可以套用第七公式集解决。

后二棱:在操作完第二棱后,时刻追踪后二棱的位置,使用bfs将后二棱放到UF、UB位置,套用后二棱公式解决。

棱块的状态更新:与三阶大致相同,其中Xw为特殊符号(X是UDFBLR中的任意一个),编码方式是两位,X的ASCII码减64再除以3最后加10。

至此,五阶魔方降阶完成。