用C++写CFOP求解三阶魔方的基础理念以及可行性验证

写在正文前
由于本域没有专门的讨论区,所以占用了P1000的讨论区来发表论文

本文介绍的是通过C++语言使用CFOP速拧方法来求解三阶魔方的基础理念及可行性验证。目标是通过C++写出一个程序来读取一颗三阶魔方的打乱状态,并最终输出魔方的CFOP解法。

程序要分两部分讨论,即魔方状态的存储与求解魔方的算法。
存储方面,我采用三种存储方式。第一种是简单存储魔方的六个面,维护六个二维数组(Up,Down,Front,Back,Left,Right),数组中的每个元素都是一个char类型的变量(U,D,F,B,L,R),数组的方向就是cstimer打乱展开图的方向,大体长这样:

      * * *
      * U *
      * * *
* * * * * * * * * * * *
* L * * F * * R * * B *
* * * * * * * * * * * *
      * * *
      * D *
      * * *

第二种是对于角块和棱块的存储,每个元素都是一个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]的位置”,至于为什么会采取这种奇怪的存储法,在后面的CROSS算法中会详细解释。
至此,存储问题解决了,对于每次转动也很好操作,通过模拟法就可以对魔方进行UDFBLRxyzMESudfblr及其反转(U')及其二次转动(U2),在转体之后,对魔方进行遍历修改,以保证魔方整体坐标不变,例如y'之后,L变成F等等。

CROSS
在cross这一步,我采取的方法是BFS,但如果采取的是每次分出18个分支的常规暴搜,时间复杂度高到难以想象,以最高步数8步来算,每次转动20个色块,对56个色块进行hash,时间复杂度O((20+54)*(18^1+...+18^8)),空间复杂度O((54+8)*18^8)。此时我们先前的第3种存储就能派上用场,即对四个棱块进行hash,避免R'FRF'的转动产生,最终共有A(12,4)*2^4种状态参与穷举,甚至对于每个节点的存储都可以舍弃6面存储,只使用第三种存储,时间复杂度O((4+4)*(A(12,4)*2^4-1)),以CSP测评机算力来看,仅需5.677s,空间复杂度O((16+12)*(A(12,4)*2^4)),约8.327GB。至少比之前的0.532小时,636GB好得多。

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,结束。
鄙人不才,还请各路大神多多指教

至此,可行性验证通过,感谢多天以来徐嘉昊和花子轩的陪伴。CFOP代码很长,初步估计大约有100kB左右,录入公式本也是很煎熬的过程,在B站上,我将在7月31日用大号发布代码展示视频与教程,将在6月25日用小号开直播搓代码
我B站大号:@DJI大疆技木支持 小号:@DJI大彊技木支持 小小号:@盛泽三中

0 条评论

目前还没有评论...

信息

ID
1000
难度
7
分类
(无)
标签
递交数
1559
已通过
291
通过率
19%
被复制
29
上传者