一,双面数局
最强大脑 同款项目
二,计算机求解
1,交换公式
2,通用操作
cpp
vector<Opt> getOpts(int n)
{
vector<int>v0;
for (int i = 0; i < n*n * 2; i++)v0.push_back(i);
vector<Opt>ans;
for (int i = 0; i < n; i++) {
string optName = "第";
optName += std::to_string(i + 1);
optName += "行往右";
vector<int>v = v0;
int s1 = i * n, s2 = i * n + n * n;
vector<int>nums;
for (int i = s1; i < s1 + n; i++)nums.push_back(i);
for (int i = s2; i < s2 + n; i++)nums.push_back(i);
for (int i = 0; i < nums.size(); i++)v[nums[(i + 1) % nums.size()]] = nums[i];
Opt opt{ { v } ,optName };
ans.push_back(opt);
}
for (int i = 0; i < n; i++) {
string optName = "第";
optName += std::to_string(i + 1);
optName += "列往下";
vector<int>v = v0;
int s1 = i, s2 = n * n * 2 - i - 1;
vector<int>nums;
for (int i = s1; i < s1 + n * n; i += n)nums.push_back(i);
for (int i = s2; i > s2 - n * n; i -= n)nums.push_back(i);
for (int i = 0; i < nums.size(); i++)v[nums[(i + 1) % nums.size()]] = nums[i];
Opt opt{ { v } ,optName };
ans.push_back(opt);
}
return ans;
}
3,n=2
cpp
int main()
{
int n = 2;
CubeBlock block1(0, n * n * 2);
vector<CubeBlock>b = vector<CubeBlock>{ block1 };
vector<Opt> v = getOpts(n);
CubeOpt op1(b, v[0]);
CubeOpt op2(b, v[1]);
CubeOpt op3(b, v[2]);
CubeOpt op4(b, v[3]);
vector<CubeOpt>opts = { op1,op2,op3,op4 };
for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
Cube cube(b, opts);
cube.bfs(0, 2, 2);
return 0;
}
输出:
2,1,0,3,4,5,6,7,
0第1行往右 0第1行往右 1第2行往右 2第1列往下 0第1行往右 1第2行往右 2第1列往下 1第2行往右 2第1列往下 0第1行往右 3第2列往下
这是交换0和2的公式
4,n=3
cpp
int main()
{
int n = 3;
CubeBlock block1(0, n * n * 2);
vector<CubeBlock>b = vector<CubeBlock>{ block1 };
vector<Opt> v = getOpts(n);
CubeOpt op1(b, v[0]);
CubeOpt op2(b, v[1]);
CubeOpt op3(b, v[2]);
CubeOpt op4(b, v[3]);
CubeOpt op5(b, v[4]);
CubeOpt op6(b, v[5]);
vector<CubeOpt>opts = { op1,op2,op3,op4,op5,op6 };
for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
Cube cube(b, opts);
cube.bfs(0, 2, 2);
return 0;
}
输出:
0,1,7,3,4,5,6,2,8,9,10,11,12,13,14,15,16,17,
0第1行往右 0第1行往右 4第2列往下 1第2行往右 1第2行往右 1第2行往右 4第2列往下 4第2列往下 0第1行往右 0第1行往右 0第1行往右 0第1行往右 0第1行往右 1第2行往右 1第2行往右 0第1行往右 0第1行往右 0第1行往右 0第1行往右 0第1行往右 1第2行往右
这是交换2和7的公式
化简结果:
第1行往右 *2
第2列往下
第2行往右*3
第2列往下*2
第1行往左*2
第2行往右*3





5,n=4
代码1:略
运行结果:得到0 18 19 23交换的公式(不是1个4阶置换,而是2个2阶置换)
代码2:
cpp
int main()
{
int n = 4;
CubeBlock block1(0, n * n * 2);
vector<CubeBlock>b = vector<CubeBlock>{ block1 };
vector<Opt> v = getOpts(n);
CubeOpt op1(b, v[0]);
CubeOpt op2(b, v[1]);
CubeOpt op3(b, v[2]);
CubeOpt op4(b, v[3]);
CubeOpt op5(b, v[4]);
CubeOpt op6(b, v[5]);
CubeOpt op7(b, v[6]);
CubeOpt op8(b, v[7]);
Opt opt9{ { {19,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,23,0,20,21,22,18,24,25,26,27,28,29,30,31} } ,"【1下1右1上1左】" };
CubeOpt op9(b, opt9);
vector<CubeOpt>opts = { op1,op2,op3,op4,op5,op6,op7,op8,op9 };
for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
Cube cube(b, opts);
cube.bfs(0, 2, 3);
return 0;
}
输出:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,21,19,20,22,18,23,24,25,26,27,28,29,30,31,
1第2行往右 6【1下1右1上1左】 1第2行往右 6【1下1右1上1左】 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右
这是18-22-21三者轮换(顺时针旋转)的公式
化简结果:
第2行往右
【1下1右1上1左】
第2行往右
【1下1右1上1左】
第2行往左*2
我们把这个公式记作三轮换公式。
代码3:
cpp
int main()
{
int n = 4;
CubeBlock block1(0, n * n * 2);
vector<CubeBlock>b = vector<CubeBlock>{ block1 };
vector<Opt> v = getOpts(n);
CubeOpt op1(b, v[0]);
CubeOpt op2(b, v[1]);
CubeOpt op3(b, v[2]);
CubeOpt op4(b, v[3]);
CubeOpt op5(b, v[4]);
CubeOpt op6(b, v[5]);
CubeOpt op7(b, v[6]);
CubeOpt op8(b, v[7]);
Opt opt9{ { {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,21,19,20,22,18,23,24,25,26,27,28,29,30,31} } ,"三轮换" };
CubeOpt op9(b, opt9);
vector<CubeOpt>opts = { op2,op9 };
for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
Cube cube(b, opts);
cube.bfs(0, 2, 2);
return 0;
}
输出:
0,1,2,3,4,6,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右
这是交换5和6的公式。
化简结果:
第2行往右
【2右1下1右1上1左】 *4
第2行往右
【2右1下1右1上1左】 *4
第2行往左
其中,2右就是第2行往右,以此类推。
同理,还有交换4和7的公式:
第2行往右*3
【1下1右1上1左】
第2行往右
【1下1右1上1左】
第2行往右 *2
【1下1右1上1左】
第2行往右
【1下1右1上1左】
第2行往左*2
【1下1右1上1左】
第2行往右
【1下1右1上1左】
第2行往右 *2
【1下1右1上1左】
第2行往右
【1下1右1上1左】
第2行往右
【1下1右1上1左】
第2行往右
【1下1右1上1左】
第2行往左*2






三,高阶场景
前面的校验,基本上已经形成固定的模式了,只需要数字改一改就能得到高阶的公式了。
和魔方不同的是,魔方是公式本身进行微调即可得到新公式,而双面数局是产生n=k的公式的代码微调即可得到产生n=k+1的公式的代码,但n=k的公式和n=k+1的公式之间差别还是挺大的。
1,通用操作
我们把"1下1右1上1左"这个小公式进行参数化,避免手动输入置换表
cpp
vector<Opt> getOpts(int n)
{
vector<int>v0;
for (int i = 0; i < n*n * 2; i++)v0.push_back(i);
vector<Opt>ans;
for (int i = 0; i < n; i++) {
string optName = "第";
optName += std::to_string(i + 1);
optName += "行往右";
vector<int>v = v0;
int s1 = i * n, s2 = i * n + n * n;
vector<int>nums;
for (int i = s1; i < s1 + n; i++)nums.push_back(i);
for (int i = s2; i < s2 + n; i++)nums.push_back(i);
for (int i = 0; i < nums.size(); i++)v[nums[(i + 1) % nums.size()]] = nums[i];
Opt opt{ { v } ,optName };
ans.push_back(opt);
}
for (int i = 0; i < n; i++) {
string optName = "第";
optName += std::to_string(i + 1);
optName += "列往下";
vector<int>v = v0;
int s1 = i, s2 = n * n * 2 - i - 1;
vector<int>nums;
for (int i = s1; i < s1 + n * n; i += n)nums.push_back(i);
for (int i = s2; i > s2 - n * n; i -= n)nums.push_back(i);
for (int i = 0; i < nums.size(); i++)v[nums[(i + 1) % nums.size()]] = nums[i];
Opt opt{ { v } ,optName };
ans.push_back(opt);
}
string optName = "1下1右1上1左";
vector<int>v = v0;
v[0] = n * n + n - 1, v[n * n + n - 1] = 0;
v[n * n + n - 2] = n * n + n * 2 - 1, v[n * n + n * 2 - 1] = n * n + n - 2;
Opt opt{ { v } ,optName };
ans.push_back(opt);
return ans;
}
2,n=5
代码1:
cpp
int main()
{
int n = 5;
CubeBlock block1(0, n * n * 2);
vector<CubeBlock>b = vector<CubeBlock>{ block1 };
vector<Opt> v = getOpts(n);
CubeOpt op1(b, v[0]);
CubeOpt op2(b, v[1]);
CubeOpt op3(b, v[2]);
CubeOpt op4(b, v[3]);
CubeOpt op5(b, v[4]);
CubeOpt op6(b, v[5]);
CubeOpt op7(b, v[6]);
CubeOpt op8(b, v[7]);
CubeOpt op9(b, v[8]);
CubeOpt op10(b, v[9]);
CubeOpt op11(b, v[10]);
vector<CubeOpt>opts = { op1,op2,op11 };
for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
Cube cube(b, opts);
cube.bfs(0, 2, 3);
return 0;
}
输出:
0,1,2,3,4,28,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,34,29,30,31,32,33,5,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 21下1右1上1左 1第2行往右 21下1右1上1左
这是一个三轮换的公式。
化简结果:
第2行往左
【1下1右1上1左】
第2行往右
【1下1右1上1左】
代码2:
cpp
int main()
{
int n = 5;
CubeBlock block1(0, n * n * 2);
vector<CubeBlock>b = vector<CubeBlock>{ block1 };
vector<Opt> v = getOpts(n);
CubeOpt op1(b, v[0]);
CubeOpt op2(b, v[1]);
CubeOpt op3(b, v[2]);
CubeOpt op4(b, v[3]);
CubeOpt op5(b, v[4]);
CubeOpt op6(b, v[5]);
CubeOpt op7(b, v[6]);
CubeOpt op8(b, v[7]);
CubeOpt op9(b, v[8]);
CubeOpt op10(b, v[9]);
CubeOpt op11(b, v[10]);
Opt opt{ { {0,1,2,3,4,28,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,34,29,30,31,32,33,5,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49} } ,"三轮换" };
CubeOpt op12(b, opt);
vector<CubeOpt>opts = { op2,op12 };
for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
Cube cube(b, opts);
cube.bfs(0, 2, 2);
return 0;
}
输出1:
0,1,2,3,4,5,6,8,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换
这是交换7和8的公式
化简结果:
【2右1下1右1上1左】 *6
第2行往右
【2右1下1右1上1左】 *4
输出2:
0,1,2,3,4,5,6,9,8,7,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 1三轮换 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换
这是交换7和9的公式
化简结果:
【2右1下1右1上1左】 *6
第2行往左
【2右1下1右1上1左】 *2
第2行往左*2
【2右1下1右1上1左】 *6






