目录
极光闪蝶魔方

1,魔方三要素
(1)组成部件
共126个部件,分为5组,上图的序号1-5分别是大圆块、小圆块、棱块、中心尖块、中心小块
大圆块是4*6=24个,每种颜色的4个是一样的
小圆块是4*6=24个,每种颜色的4个是一样的
棱块是24个,都不一样
中心尖块是8*6=4*12=48,每种颜色有4个一样的和另外4个一样的
中心小块是6个,都不一样
整个魔方的第一种理解方式:大正方形+大角块
大圆块、棱块组成8个大角块,每个大角块6个部件,一共48个部件
中心尖块、中心小块、小圆块组成6个面的大正方形,每个大正方形14个部件,一共78个部件
第二种理解方式:飞镖+翅膀+中心小块
棱块、中心尖块组成12个飞镖,每个飞镖6个部件,一共72个部件
大圆块、小圆块组成24片翅膀,每一片2个部件,一共48个部件
中心小块,一共6个部件
(2)可执行操作
分为3类操作
第一类是斜转60度,实现正方体和非正方体之间的切换,这一类有4种操作,因为有4个轴(同枫叶魔方)
第二类是正方体状态下,圆盘旋转某个角度,不考虑角度参数的前提下,这一类有12种操作
第三类是非正方体状态下,圆盘旋转某个角度,不考虑角度参数的前提下,每一种非正方体状态下有6种操作。
第一类操作的限制:外形曲线需要吻合,有特例1。
第二类和第三类操作的限制:外形曲线需要吻合,有特例2。
特例1:

这种情况下,也可以执行斜转60度。左边一半不动的情况下,右边一半只能顺时针旋转,不能逆时针旋转。
理论上,这种情况也可以认为是满足某种外形曲线吻合的情况,但是需要把曲线吻合重新定义,需要定义单向吻合的概念,比较麻烦。
所以我们就直接认为,这个是特例就行。
特例2:

这种情况下,右边的圆盘无法转动。
比如右边的圆盘想逆时针转动,那么1号小圆块和2号大圆块就会撞上。
(3)目标态
外形恢复正方体,且六个面都是纯色。
2,复原方法一(初始方案)
PS:《复原方法一》这一章节的所有图是2次复原过程的图混合起来的,每张图会标注S1或者S2
S2:

(1)棱块平衡
S1:

这个圆盘只有1个棱块。
恢复成每个圆盘都是2个棱块
S2:

(2)恢复所有飞镖外形
这一步其实可以再细分为2步。
先恢复棱块:
S2:

再恢复中心尖块。
这一步要区分中心尖块的奇偶性,需要恢复的中心尖块一定是奇偶平衡的。每一对奇的中心尖块和偶的中心尖块都可以一起恢复。
恢复之后:
S2:

S1:

(3)恢复正方体外形
没有总结特定的公式,找到规律很容易达成只剩最后两个部件需要调整的情况。
再多尝试几次就可以恢复成正方体:
S2:

(4)恢复所有的双尖块
即,同色的2个互为镜像的中心尖块挪到一起。
这里需要一个双半圆盘交换公式。
公式示例:
S2:


在正方体外形下,把2个圆盘旋转到上图所示的角度,这样就可以把2个圆盘进行杂交,原本是白红+白橙、红蓝+白红,共1个双尖块已恢复,杂交之后变成白红+白红、红蓝+白橙,共2个双尖块已恢复。
由于每一面都有四个中心尖块不需要区分,镜面的另外四个中心尖快之间也不需要区分,所以这一步只需要这一个公式就很容易完成。
S1:

(5)复原4个大正方形
即,把所有小圆块和中心尖块都挪到对应颜色中心小块旁边,复原4个大正方形,留下相邻2个面的大正方形。
对于双尖块,只需要一个公式:
S1:

按照图示的1234或者4321,即可把一个双尖块移动到相邻位置。这样,就可以移动到任意位置。
对于小圆块,同样只需要1个公式:
S1:

按照图示的123或者321,即可把一个小圆块移动到相邻位置。这样,就可以移动到任意位置。
S2:

(6)复原最后2个大正方形
S1:

只需要不停的在这2个面之间的相交处,把圆盘旋转180度,即互相交换3个部件,即可完成最后2个大正方形。
制作跳转表:
//通用的数据缓存去重编号方案
template<typename T>
class GetSingleId
{
public:
int id(T x) //所有元素按照首次传入顺序编号0,1,2......
{
auto it = m.find(x);
if (it != m.end())return it->second;
mr[n] = x;
return m[x] = n++;
}
int num() //id()==num()-1表示是新元素,否则是重复元素
{
return n;
}
T getData(int id) //根据id获取元素数据
{
return mr[id];
}
private:
map<T, int>m;
map<int, T>mr;
int n = 0;
};
vector<vector<int>> getNext(vector<int>& v)
{
vector<vector<int>> ans;
for (int i = 0; i < 8; i += 2) {
for (int j = 0; j < 8; j += 2) {
auto v2 = v;
for (int k = 0; k < 3; k++) {
int id1 = (i + k) % 8, id2 = (j + k) % 8 + 8;
v2[id1] ^= v2[id2] ^= v2[id1] ^= v2[id2];
}
ans.push_back(v2);
}
}
return ans;
}
void bfs(vector<int>& v)
{
GetSingleId<vector<int>>opt;
opt.id(v);
set<vector<int>>s;
s.insert(v);
queue<vector<int>>q;
q.push(v);
map<int, int>m;
m[0] = 0;
while (!q.empty()) {
auto v = q.front();
q.pop();
int fa = opt.id(v);
auto ans = getNext(v);
for (auto v : ans) {
if (s.find(v) == s.end()) {
s.insert(v);
q.push(v);
m[opt.id(v)] = fa;
}
}
}
for (int i = 0; i < s.size();i++) {
cout << "序号=" << i << " ";
auto v = opt.getData(i);
for (auto x : v)cout << x << " ";
cout << " 跳转到序号" << m[i] << endl;
}
}
int main()
{
vector<int> v{ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1 }; //前8个是一面的顺时针编号,从小圆块开始,后8个同理
bfs(v);
return 0;
}
输出结果:
序号=0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 跳转到序号0
序号=1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 跳转到序号0
序号=2 1 1 1 0 0 0 0 0 1 1 0 0 0 1 1 1 跳转到序号0
序号=3 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 跳转到序号0
序号=4 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 跳转到序号0
序号=5 0 0 1 1 1 0 0 0 0 0 0 1 1 1 1 1 跳转到序号0
序号=6 0 0 1 1 1 0 0 0 1 1 0 0 0 1 1 1 跳转到序号0
序号=7 0 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 跳转到序号0
。。。。。。
序号=4893 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 跳转到序号3493
序号=4894 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 跳转到序号3512
序号=4895 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 跳转到序号3570
序号=4896 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 1 跳转到序号3661
序号=4897 1 0 1 0 0 1 0 1 0 1 1 0 1 0 0 1 跳转到序号3718
序号=4898 1 0 1 0 0 1 0 1 0 1 0 1 1 0 1 0 跳转到序号3889
序号=4899 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 跳转到序号4500
一共4900种情况,也就是70*70,其中70就是C(8,4)
所以,所有的情况都是可达的
使用示例:
S1:

按照0橙1黄编号,上面是1 1 0 0 0 0 0 0下面是1 0 1 1 1 1 0 1
加起来就是1 1 0 0 0 0 0 0 1 0 1 1 1 1 0 1
所以答案就是:
序号=167 1 1 0 0 0 0 0 0 1 0 1 1 1 1 0 1 跳转到序号17
序号=17 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 跳转到序号1
序号=1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 跳转到序号0
S1:

S2:

(7)恢复4个大角块中的3个棱块
首先就有个问题,3个棱块组成1个大角块,一定要按照标准色排布吗?
有没有可能镜像色也可以?(其他的颜色排布显然不行)
这个问题,下面有专门的章节分析。
恢复大角块需要一个双棱交换公式,共7步

前4步是按照12345的顺序,把顶层右边的双尖块挪到顶层左边,后3步是按照4321的顺序把被挤出来的双尖块又挪到顶层右边。
效果就是这2个棱互换:

只需要这个公式和它的镜像版本,就可以恢复所有大角块中的3个棱块。
根据斜转魔方的规律,只需要上层是1234,下层就一定是5678

所以,我们拼凑大角块也需要按照1234+5678的顺序。
前4个大角块,只需要奇偶性对应上就行,即2号大角块和3号大角块都需要和1号大角块相邻,而4号大角块需要和2号大角块相邻。
这一步我没贴图,直接看下图看的更清楚(下面一步的存在就是为了看的更清楚)
(8)复原4个大角块的位置
不看6个大正方形的位置,只看4个大角块的位置关系,而且也不看大角块的朝向。
S1:

根据这4个大角块的位置,剩下的4个大角块的12个棱块,每个块属于哪个位置的大角块也就确定了,必须按照这个关系去拼凑剩下的4个大角块。
(9)再恢复2个大角块中的3个棱块
此时,只剩最后2个大角块了。
这一步我没贴图,直接看下图看的更清楚(下面一步的存在就是为了看的更清楚)
(10)按照斜转魔方去复原
这一步是否可以简化成,只复原6个大角块的位置?
这个我没深入研究,答案取决于斜转魔方中心块的位置和角块位置加朝向之间的深层次逻辑关系。
根据简单的推理,中心块的位置是mod 2的,而角块的朝向是mod 3的,所以应该不用管角块的朝向。而无论中心块的位置情况如何,只需要上层角块是1234,下层就一定是5678,所以应该也不需要管中心块的位置。
只复原6个大角块的位置:
S1:

这里的123456号大角块的位置复原了,12345号的朝向也是正确的,6号需要逆时针旋转。
(11)恢复最后2个大角块中的3个棱块
S1:

看起来,只需要把图片中标注的3号和4号这2个棱块一交换就结束了,实则不然,这里我们需要分析大角块的朝向了。
按照斜转魔方的规律,8个角块和6个中心块的位置正确时,所有角块需要旋转的次数总和一定是3的倍数。中心块的位置是mod 2的,而角块的朝向是mod 3的,所以和中心块的位置也无关。当前角块位置全部复原,那么7号和8号应该是一个不需要旋转,一个需要顺时针旋转。
根据这个规律重新规划这6个棱块之间的交换需求就是:123456变成124563。
而我们已有的公式就是在2个相邻的大角块之间互换棱块,所以这里的长度为6的序列每次只能在左边3个里面选一个,右边3个里面选1个,完成一次互换。
所以最短交换路径之一就是:123456->126453->125463->124563
这样就完成了最后2个大角块种的棱块:
S1:

另一个示例:
S2:


图中顶层最终会变成黄色,而1号的朝向要调成,需要逆时针旋转,2号的朝向要调成,不需要旋转(即朝上)。
所以交换需求就是:123456变成125634
交换路径就是123456->126453->124653->123654->125634
(12)复原8个大角块
这一步其实就是需要调整大圆块的位置。
首先我们把双棱互换公式做一个变形,原本是7步:

效果即交换1号和2号棱块:
S1:

我们在这7步前面加2步,即3->4->2,这7步后面加2步,即2->4->3
这样就得到了一个11步的公式,效果是3号和1号这2个棱互换,即不同的角块之间点相邻的2个棱块的互换,我们称之为相邻棱互换公式。
然后我们再用4个相邻棱互换公式,直接组成1个三大圆块交换公式。
S1:

如图,先做1和2之间的相邻棱互换公式,再做3和4之间的相邻棱互换公式,再做1和2之间的相邻棱互换公式,最后做3和4之间的相邻棱互换公式,这就是三大圆块交换公式。
效果就是上图变成了:
S1:

也就是123号3个大圆块之间发生了轮换。
由于每一种颜色的4个大圆块都是不需要区分的,所以只需要这一个公式,就可以很轻松的完成这一步。
S1:

(13)复原魔方
按照斜转魔方的方法去复原。
因为前面复原每个大角块的3个棱块时,考虑到了足够的细节,所以这一步几乎不会出现和斜转魔方不同的情况,但还是有2个例外。
第一个例外就是8个大角块和6个大正方形的奇偶性不一致。
奇偶性一致时:
S1:

奇偶性不一致时:
S2:


也就是说,只有2个大正方形反了,其他的都复原了,这种情况按照斜转魔方是无法复原的情况。
处理方法:
把8个大角块分为白色面4个和黑色面4个,一一对应,两两互换位置,然后再按照上面的方法重复复原即可。
第二个例外就是最后只剩2个角块的朝向无法复原,因为前面只考虑了所有角块需要旋转的次数总和一定是3的倍数。

处理方法:
首先利用棱块交换,把2个大角块的朝向调整过来。

这个时候就只差6个大圆块了。
用4次三大圆块互换公式,即可直接复原。
3,复原方法二(优化方案)
(1)棱块平衡
同复原方法一
(2)恢复所有飞镖外形
同复原方法一
(3)恢复正方体外形
同复原方法一
(4)恢复所有的双尖块
同复原方法一
(5)复原4个大正方形
同复原方法一
(6)复原最后2个大正方形
同复原方法一
(7)颜色定位
也就是把6个大正方形按照标准颜色排布复原位置。
(8)恢复1个大角块中的3个棱块
这一步需要根据6个面的颜色,确定一个大角块的位置(或者只确定奇偶性也行),然后在正确的位置去恢复3个棱块。

如图,白蓝红这个大角块就拼好了(不用管大圆块,我这里是碰巧三个都吻合)
(9)再恢复3个大角块中的3个棱块
接下来三个大角块位置的奇偶性,只需要参照上面的白蓝红这个大角块就行了,不用再管中心块的位置了。
(10)复原4个大角块的位置
同复原方法一
(11)再恢复2个大角块中的3个棱块
同复原方法一中的“(9)再恢复2个大角块中的3个棱块”
(12)复原6个大角块的位置
同复原方法一中的“(10)按照斜转魔方去复原”
(13)恢复最后2个大角块中的3个棱块
最后2个大角块的朝向,都是根据另外3个位置奇偶性相同的大角块的朝向确定的。
也就是说,4个大角块需要旋转的次数总和一定是3的倍数,另外4个大角块需要旋转的次数总和一定是3的倍数。
(14)复原8个大角块
同复原方法一
(15)复原魔方
按照斜转魔方的方法去复原,不会出现不一样的情况。
4,是否可以拼成镜像
可以。

虽然2种颜色排布都可以,但是从一开始,还是要选择固定的一种作为目标。
无特殊说明时,我们选择的还是标准色排布,而不是上图这个镜面色。

774

被折叠的 条评论
为什么被折叠?



