目录
一,二阶魔方
参考二阶魔方网页版

二,网页程序统一模型
因为网页版完全是AI生成的,我没有参与编码,只做了微调,所以本质上是AI完成的建模。
但是还是有必要自己建模,核对细节。
1,配色
按照标准配色,上白下黄左绿右蓝前红后橙,分别对应字母WYGBRO

2,视角
采用固定视角,不支持任意角度旋转。
正方体显示了上面、前面、右面,镜子显示了下面的一部分。
3,旋转操作
6个面 上下左右前后 对应 UDLRFB
6个顺时针操作即 UDLRFB
6个逆时针操作即U'D'L'R'F'B'
4,整体旋转操作

x y z分别表示右面、前面、上面视角的顺时针旋转。
x' y' z'分别表示对应的逆时针旋转。
5,编码

,
三,校验程序
1,统一模型
6个面的编码:按照上下左右前后的顺序,依次组成代码中的vector<vector<vector<char>>> cube,每个面都是一个正方形的二维数组。
2,完整代码
#include <iostream>
#include <string_view>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <array>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <iomanip>
#include <cmath>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
#include <thread>
using namespace std;
class SingleVectorOpt
{
public:
//翻转vector、翻转二维vector的每一行
template<typename T>
static vector<T> frev(const vector<T>& v)
{
vector<T> ans;
ans.resize(v.size());
for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
return ans;
}
template<typename T>
static vector<vector<T>> frev(const vector<vector<T>>& v)
{
vector<vector<T>>ans;
for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
return ans;
}
//沿主对角线(左上角到右下角)翻转二维vector
template<typename T>
static vector<vector<T>> foverturn(const vector<vector<T>>& v)
{
vector<vector<T>> ans(v[0].size());
for (int i = 0; i < v[0].size(); i++) {
ans[i].resize(v.size());
for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
}
return ans;
}
//顺时针旋转二维vector
template<typename T>
static vector<vector<T>> frotation(const vector<vector<T>>& v)
{
return frev(foverturn(v));
}
//从vector(一维或2维)中删除所有的x
template<typename T>
static void deletAllX(vector<T>& v, T x)
{
for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
}
template<typename T>
static void deletAllX(vector<vector<T>>& v, T x)
{
for (auto& vi : v)deletAllX(vi, x);
}
// 去掉相邻重复元素
template<typename T>
static void deleteNeiborSame(vector<T>& v)
{
v.erase(std::unique(v.begin(), v.end()), v.end());
}
//判断数组去掉相邻重复数之后有多少个不同的数
template<typename T>
static int getDifNum(const vector<T>& v)
{
auto v2 = v;
deleteNeiborSame(v2);
return v2.size();
}
//vector乘一个数
template<typename T1, typename T2>
static void fcheng(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
}
//vector加一个数
template<typename T1, typename T2>
static void fjia(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
}
//二维数组每一行排序
template<typename T>
static void sortEveryLine(vector<vector<T>>& v)
{
for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
}
//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
template<typename T, class P>
static inline vector<int>firstInLeft(vector<T>v, P pr)
{
vector<int> ans;
if (v.size() == 0)return ans;
stack<T>st;
st.push(0);
ans.push_back(-1);
for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
{
while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
if (st.empty())ans.push_back(-1);
else ans.push_back(st.top());
st.push(i);
}
return ans;
}
//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fminlef(vector<T> v)
{
return firstInLeft(v, [](T a, T b) {return a < b; }); //可换为自定义函数
}
//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fminlef2(vector<T> v)
{
return firstInLeft(v, [](T a, T b) {return a <= b; }); //可换为自定义函数
}
//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fmaxlef(vector<T> v)
{
fcheng(v, -1);
vector<int>ans = fminlef(v);
return ans;
}
//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fmaxlef2(vector<T> v)
{
fcheng(v, -1);
vector<int>ans = fminlef2(v);
return ans;
}
//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fminrig(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fminlef(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fminrig2(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fminlef2(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fmaxrig(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fmaxlef(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fmaxrig2(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
static map<int, map<int, int>> splitAtHalf(vector<int>& v)
{
vector<int>s;
int n = 0;
s.push_back(n);
for (auto x : v) {
n += x;
s.push_back(n);
}
map<int, map<int, int>>ans;
for (int i = 0; i < v.size(); i++) {
int id = i;
for (int j = i; j < v.size(); j++) {
while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
ans[i][j] = id;
}
}
return ans;
}
//获取所有的众数
template<typename T>
static vector<T> getMost(const vector<T>& v)
{
int n = 0;
map<T, int>m;
for (auto x : v)n = max(n, ++m[x]);
vector<T>ans;
for (auto p : m)if (p.second == n)ans.push_back(p.first);
return ans;
}
};
#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行
int N;
vector<vector<vector<char>>> Init()
{
vector<vector<vector<char>>> ans;
for (auto c : { 'W','Y','G','B','R','O' }) //上下左右前后
{
vector<char> temp(N, c);
vector<vector<char>>v(N, temp);
ans.push_back(v);
}
return ans;
}
void show(vector<vector<vector<char>>>& cube)
{
cout << endl << "U: ";
for (auto v : cube[0])for (auto ch : v)cout << ch;
cout << endl << "D: ";
for (auto v : cube[1])for (auto ch : v)cout << ch;
cout << endl << "L: ";
for (auto v : cube[2])for (auto ch : v)cout << ch;
cout << endl << "R: ";
for (auto v : cube[3])for (auto ch : v)cout << ch;
cout << endl << "F: ";
for (auto v : cube[4])for (auto ch : v)cout << ch;
cout << endl << "B: ";
for (auto v : cube[5])for (auto ch : v)cout << ch;
cout << endl;
}
void rotate(vector<vector<vector<char>>>& cube, string c)
{
if (c[1] == '\'') {
string c2;
c2 += c[0];
rotate(cube, c2);
rotate(cube, c2);
rotate(cube, c2);
return;
}
if (c == "U")
{
cube[0] = Frotation(cube[0]);
auto v = cube[2][0];
cube[2][0] = cube[4][0], cube[4][0] = cube[3][0], cube[3][0] = cube[5][0], cube[5][0] = v;
return;
}
if (c == "D") {
rotate(cube, "x");
rotate(cube, "x");
rotate(cube, "U");
rotate(cube, "x");
rotate(cube, "x");
return;
}
if (c == "R")
{
rotate(cube, "y'");
rotate(cube, "U");
rotate(cube, "y");
return;
}
if (c == "L")
{
rotate(cube, "y");
rotate(cube, "U");
rotate(cube, "y'");
return;
}
if (c == "F")
{
rotate(cube, "x");
rotate(cube, "U");
rotate(cube, "x'");
return;
}
if (c == "B")
{
rotate(cube, "x'");
rotate(cube, "U");
rotate(cube, "x");
return;
}
if (c == "x")
{
cube[3] = Frotation(cube[3]);
cube[2] = Frotation(Frotation(Frotation(cube[2])));
auto v = cube[0];
cube[0] = cube[4];
cube[4] = Frev<vector<char>>(cube[1]); //上下翻转
cube[1] = Frev<char>(cube[5]); //翻转每一行
cube[5] = Frev<char>(Frev<vector<char>>(v));
return;
}
if (c == "z") {
cube[0] = Frotation(cube[0]);
cube[1] = Frotation(cube[1]);
auto v = cube[2];
cube[2] = cube[4], cube[4] = cube[3], cube[3] = cube[5], cube[5] = v;
return;
}
if (c == "y") {
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "x");
rotate(cube, "z");
return;
}
}
void test1() //输入所有操作,只显示最终结果
{
vector<string>opts;
string c;
while (cin >> c)opts.push_back(c);
auto cube = Init();
for (auto c : opts) {
rotate(cube, c);
}
show(cube);
}
void test2() //每次输入1个操作,实时显示结果
{
auto cube = Init();
string c;
while (cin >> c) {
rotate(cube, c);
show(cube);
cout << endl;
}
}
int main()
{
N = 2;
test1();
return 0;
}
3,使用方法
任意时刻,只需要把完整序列一次性输入进去,即可得到当前局面。
例如:


输出的当前局面直接和html的当前局面对比,所有字符一模一样则校验通过。
这就完成了证明:AI输出的html程序、我纯手写的校验程序已经没有BUG了,且相关的所有模型都保持了一致。
四,二阶魔方手动复原
就用上面的这个打乱序列,手动复原之后得到操作序列:
F' D R U' L' F' L D' U' B U' L B' R' F R' D' B R B D' L' B L' D R z z R' z D z B R B' z' F D' B' L' B L' F' L y y z z F U F' U F U U F' z z z z U z z z z R R F F R' B' R R R' F F R R R B R' z z z z' z z z R R F F R' B' R F F R' B R'
校验:

校验通过。
五,三阶魔方
1,网页版程序
参考三阶魔方网页版
2,打乱校验
int main()
{
N = 3;
test1();
return 0;
}


校验通过。
PS:需不需要check当前局面和显示的魔方是否对应?不需要,二阶魔方check过,后面所有魔方都不需要了,因为我们的最终目的是探索怎么样生成一个操作序列来复原魔方,而最终得到的操作序列是否真的能复原,只需要使用校验程序即可,和界面显示无关。
3,录入公式
录入9个公式
// 白色角块1 y' F R' F' y D D y' F R F' y // 白色角块2 y' F R F' y // 白色角块3 R' D' R // 中层棱块1 U' L' U L U F U' F' // 中层棱块2 U R U' R' U' F' U F // 顶层十字 F R U R' U' F' // 小鱼1 R' U' R U' R' U U R // 小鱼2 F U F' U F U U F' // 换角 R R F F R' B' R F F R' B R'

4,手动复原
【完整操作序列】 F' U B U L R' L B' U' B' D' F L F' B U' R F' U' L' F' L' U B L' F' U R U F' U' z z U U F' U z z U U R z y' F R F' y U y' F R' F' y D D y' F R F' y z z' z D y' F R F' y z y' F R F' y D' y' F R F' y U U y y z U' z U R U' R' U' F' U F z z U' L' U L U F U' F' U' z U' L' U L U F U' F' z U U z' U R U' R' U' F' U F z z z z F U F' U F U U F' z R R F F R' B' R F F R' B R' U' z R' U' R U' R' U U R z z F U F' U F U U F'
校验:

校验通过。
到这一步,也顺便验证了这9个公式的正确性,可以用于自动复原了。
5,自动复原
#include <iostream>
#include <string_view>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <array>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <iomanip>
#include <cmath>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
#include <thread>
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
class SingleVectorOpt
{
public:
//翻转vector、翻转二维vector的每一行
template<typename T>
static vector<T> frev(const vector<T>& v)
{
vector<T> ans;
ans.resize(v.size());
for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
return ans;
}
template<typename T>
static vector<vector<T>> frev(const vector<vector<T>>& v)
{
vector<vector<T>>ans;
for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
return ans;
}
//沿主对角线(左上角到右下角)翻转二维vector
template<typename T>
static vector<vector<T>> foverturn(const vector<vector<T>>& v)
{
vector<vector<T>> ans(v[0].size());
for (int i = 0; i < v[0].size(); i++) {
ans[i].resize(v.size());
for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
}
return ans;
}
//顺时针旋转二维vector
template<typename T>
static vector<vector<T>> frotation(const vector<vector<T>>& v)
{
return frev(foverturn(v));
}
//从vector(一维或2维)中删除所有的x
template<typename T>
static void deletAllX(vector<T>& v, T x)
{
for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
}
template<typename T>
static void deletAllX(vector<vector<T>>& v, T x)
{
for (auto& vi : v)deletAllX(vi, x);
}
// 去掉相邻重复元素
template<typename T>
static void deleteNeiborSame(vector<T>& v)
{
v.erase(std::unique(v.begin(), v.end()), v.end());
}
//判断数组去掉相邻重复数之后有多少个不同的数
template<typename T>
static int getDifNum(const vector<T>& v)
{
auto v2 = v;
deleteNeiborSame(v2);
return v2.size();
}
//vector乘一个数
template<typename T1, typename T2>
static void fcheng(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
}
//vector加一个数
template<typename T1, typename T2>
static void fjia(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
}
//二维数组每一行排序
template<typename T>
static void sortEveryLine(vector<vector<T>>& v)
{
for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
}
//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
template<typename T, class P>
static inline vector<int>firstInLeft(vector<T>v, P pr)
{
vector<int> ans;
if (v.size() == 0)return ans;
stack<T>st;
st.push(0);
ans.push_back(-1);
for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
{
while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
if (st.empty())ans.push_back(-1);
else ans.push_back(st.top());
st.push(i);
}
return ans;
}
//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fminlef(vector<T> v)
{
return firstInLeft(v, [](T a, T b) {return a < b; }); //可换为自定义函数
}
//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fminlef2(vector<T> v)
{
return firstInLeft(v, [](T a, T b) {return a <= b; }); //可换为自定义函数
}
//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fmaxlef(vector<T> v)
{
fcheng(v, -1);
vector<int>ans = fminlef(v);
return ans;
}
//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fmaxlef2(vector<T> v)
{
fcheng(v, -1);
vector<int>ans = fminlef2(v);
return ans;
}
//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fminrig(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fminlef(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fminrig2(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fminlef2(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fmaxrig(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fmaxlef(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fmaxrig2(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
static map<int, map<int, int>> splitAtHalf(vector<int>& v)
{
vector<int>s;
int n = 0;
s.push_back(n);
for (auto x : v) {
n += x;
s.push_back(n);
}
map<int, map<int, int>>ans;
for (int i = 0; i < v.size(); i++) {
int id = i;
for (int j = i; j < v.size(); j++) {
while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
ans[i][j] = id;
}
}
return ans;
}
//获取所有的众数
template<typename T>
static vector<T> getMost(const vector<T>& v)
{
int n = 0;
map<T, int>m;
for (auto x : v)n = max(n, ++m[x]);
vector<T>ans;
for (auto p : m)if (p.second == n)ans.push_back(p.first);
return ans;
}
};
#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行
int N;
vector<vector<vector<char>>> Init()
{
vector<vector<vector<char>>> ans;
for (auto c : { 'W','Y','G','B','R','O' }) //上下左右前后
{
vector<char> temp(N, c);
vector<vector<char>>v(N, temp);
ans.push_back(v);
}
return ans;
}
void show(vector<vector<vector<char>>>& cube)
{
cout << endl << "U: ";
for (auto v : cube[0])for (auto ch : v)cout << ch;
cout << endl << "D: ";
for (auto v : cube[1])for (auto ch : v)cout << ch;
cout << endl << "L: ";
for (auto v : cube[2])for (auto ch : v)cout << ch;
cout << endl << "R: ";
for (auto v : cube[3])for (auto ch : v)cout << ch;
cout << endl << "F: ";
for (auto v : cube[4])for (auto ch : v)cout << ch;
cout << endl << "B: ";
for (auto v : cube[5])for (auto ch : v)cout << ch;
cout << endl;
}
void rotate(vector<vector<vector<char>>>& cube, string c)
{
if (c[1] == '\'') {
string c2;
c2 += c[0];
rotate(cube, c2);
rotate(cube, c2);
rotate(cube, c2);
return;
}
if (c == "U")
{
cube[0] = Frotation(cube[0]);
auto v = cube[2][0];
cube[2][0] = cube[4][0], cube[4][0] = cube[3][0], cube[3][0] = cube[5][0], cube[5][0] = v;
return;
}
if (c == "D") {
rotate(cube, "x");
rotate(cube, "x");
rotate(cube, "U");
rotate(cube, "x");
rotate(cube, "x");
return;
}
if (c == "R")
{
rotate(cube, "y'");
rotate(cube, "U");
rotate(cube, "y");
return;
}
if (c == "L")
{
rotate(cube, "y");
rotate(cube, "U");
rotate(cube, "y'");
return;
}
if (c == "F")
{
rotate(cube, "x");
rotate(cube, "U");
rotate(cube, "x'");
return;
}
if (c == "B")
{
rotate(cube, "x'");
rotate(cube, "U");
rotate(cube, "x");
return;
}
if (c == "x")
{
cube[3] = Frotation(cube[3]);
cube[2] = Frotation(Frotation(Frotation(cube[2])));
auto v = cube[0];
cube[0] = cube[4];
cube[4] = Frev<vector<char>>(cube[1]); //上下翻转
cube[1] = Frev<char>(cube[5]); //翻转每一行
cube[5] = Frev<char>(Frev<vector<char>>(v));
return;
}
if (c == "z") {
cube[0] = Frotation(cube[0]);
cube[1] = Frotation(cube[1]);
auto v = cube[2];
cube[2] = cube[4], cube[4] = cube[3], cube[3] = cube[5], cube[5] = v;
return;
}
if (c == "y") {
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "x");
rotate(cube, "z");
return;
}
}
void test1() //输入所有操作,只显示最终结果
{
vector<string>opts;
string c;
while (cin >> c)opts.push_back(c);
auto cube = Init();
for (auto c : opts) {
rotate(cube, c);
}
show(cube);
}
void test2() //每次输入1个操作,实时显示结果
{
auto cube = Init();
string c;
while (cin >> c) {
rotate(cube, c);
show(cube);
cout << endl;
}
}
#define AnsAdd(s) ans += s;ans += " "; rotate(cube, s);
#define F1 AnsAdd("y'");AnsAdd("F");AnsAdd("R'");AnsAdd("F'");AnsAdd("y");AnsAdd("D");AnsAdd("D");AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块1 y' F R' F' y D D y' F R F' y
#define F2 AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块2 y' F R F' y
#define F3 AnsAdd("R'");AnsAdd("D");AnsAdd("R");// 白色角块3 R' D' R
#define F4 AnsAdd("U'");AnsAdd("L'");AnsAdd("U");AnsAdd("L");AnsAdd("U");AnsAdd("F");AnsAdd("U'");AnsAdd("F'");// 中层棱块1 U' L' U L U F U' F'
#define F5 AnsAdd("U");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");AnsAdd("U");AnsAdd("F");// 中层棱块2 U R U' R' U' F' U F
#define F6 AnsAdd("F");AnsAdd("R");AnsAdd("U");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");// 顶层十字 F R U R' U' F'
#define F7 AnsAdd("R'");AnsAdd("U'");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U");AnsAdd("U");AnsAdd("R"); // 小鱼1 R' U' R U' R' U U R
#define F8 AnsAdd("F");AnsAdd("U");AnsAdd("F'");AnsAdd("U");AnsAdd("F");AnsAdd("U");AnsAdd("U");AnsAdd("F'"); // 小鱼2 F U F' U F U U F'
#define F9 AnsAdd("R");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B'");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B");AnsAdd("R'"); // 换角 R R F F R' B' R F F R' B R'
bool checkAllCenter(const vector<vector<vector<char>>>& cube)
{
for (int i = 0; i < 6; i++) {
char centerColor = cube[i][N / 2][N / 2];
for (int j = 1; j < N - 1; j++) {
for (int k = 1; k < N - 1; k++) {
if (cube[i][j][k] != centerColor) {
return false;
}
}
}
}
return true;
}
string makeAllCenter(vector<vector<vector<char>>>& cube)
{
if (checkAllCenter(cube))return "";
return "z"; //// 待更新
}
bool checkDir(const vector<vector<vector<char>>>& cube)
{
if (cube[0][1][1] != 'W')return false;
if (cube[2][1][1] != 'G')return false;
return true;
}
string makeDir(vector<vector<vector<char>>>& cube)
{
string ans;
if (cube[1][1][1] == 'W') {
AnsAdd("x");
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][1][1] == 'W')break;
}
if (cube[0][1][1] != 'W') {
AnsAdd("x");
}
return ans;
}
bool checkAllEdge(const vector<vector<vector<char>>>& cube)
{
for (int i = 0; i < 6; i++) {
for (int j = 1; j < N - 1; j++) {
if (cube[i][0][j] != cube[i][0][1] || cube[i][N - 1][j] != cube[i][N - 1][1] || cube[i][j][0] != cube[i][1][0] || cube[i][j][N - 1] != cube[i][1][N - 1]) {
return false;
}
}
}
return true;
}
string makeAllEdge(const vector<vector<vector<char>>>& cube)
{
if (checkAllEdge(cube))return "";
return "z"; //// 待更新
}
string makeUUUU(vector<vector<vector<char>>>& cube) //白色层方向回正
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][N - 1][1] == 'W' && cube[4][0][1] == 'R') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][1][N - 1] == 'W' && cube[3][0][1] == 'B') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][1][0] == 'W' && cube[2][0][1] == 'G') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][0][1] == 'W' && cube[5][0][1] == 'O') {
return ans;
}
}
return ans;
}
bool checkWhiteCross(const vector<vector<vector<char>>>& cube)// 检查白色十字是否完成
{
char whiteColor = 'W';
if (cube[0][0][1] != whiteColor || cube[0][N - 1][1] != whiteColor || cube[0][1][0] != whiteColor || cube[0][1][N - 1] != whiteColor) {
return false;
}
if (cube[2][0][1] != 'G' || cube[3][0][1] != 'B' || cube[4][0][1] != 'R') {
return false;
}
return true;
}
string makeWhiteCrossOnce(vector<vector<vector<char>>>& cube)
{
string ans = "";
for (int i = 0; i < 4; i++) {
AnsAdd("D");
if (cube[4][N - 1][1] == 'W') {
ans += makeUUUU(cube);
char c = cube[1][N - 1][1];
if (c == 'B') {
AnsAdd("U");
}
if (c == 'O') {
AnsAdd("U");
AnsAdd("U");
}
if (c == 'G') {
AnsAdd("U'");
}
AnsAdd("F'");
AnsAdd("U'");
AnsAdd("R");
return ans;
}
if (cube[1][N - 1][1] == 'W') {
ans += makeUUUU(cube);
char c = cube[4][N - 1][1];
if (c == 'B') {
AnsAdd("U");
}
if (c == 'O') {
AnsAdd("U");
AnsAdd("U");
}
if (c == 'G') {
AnsAdd("U'");
}
AnsAdd("F");
AnsAdd("F");
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][1][N - 1] == 'W' || cube[3][1][0] == 'W') {
while (cube[0][N - 1][1] == 'W') {
AnsAdd("U");
}
AnsAdd("F");
return ans;
}
}
ans += makeUUUU(cube);
string s = "BOGR";
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[0][N - 1][1] != 'W' || cube[4][0][1] != s[i]) {
AnsAdd("F");
AnsAdd("F");
return ans;
}
}
return ans;
}
string makeWhiteCross(vector<vector<vector<char>>>& cube)
{
string ans;
while (true) {
ans += makeDir(cube);
ans += makeUUUU(cube);
if (checkWhiteCross(cube))break;
ans += makeWhiteCrossOnce(cube);
}
return ans;
}
bool checkWhite(const vector<vector<vector<char>>>& cube)// 检查白色是否完成
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][1] || cube[i][0][N - 1] != cube[i][0][1])return false;
}
return true;
}
string makeWhiteOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("D");
ans += makeUUUU(cube);
string t;
t += cube[1][N - 1][N - 1];
t += cube[3][N - 1][0];
t += cube[4][N - 1][N - 1];
sort(t.begin(), t.end());
if (t == "BOW") {
AnsAdd("U");
}
if (t == "GOW") {
AnsAdd("U");
AnsAdd("U");
}
if (t == "GRW") {
AnsAdd("U");
AnsAdd("U");
AnsAdd("U");
}
if (cube[1][N - 1][N - 1] == 'W') {
F1;
return ans;
}
if (cube[4][N - 1][N - 1] == 'W') {
F2;
return ans;
}
if (cube[3][N - 1][0] == 'W') {
F3;
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[4][0][N - 1] != cube[4][0][1] || cube[3][0][0] != cube[3][0][1]) {
F2;
return ans;
}
}
return ans;
}
string makeWhite(vector<vector<vector<char>>>& cube)
{
string ans;
while (true) {
ans += makeDir(cube);
if (checkWhite(cube))break;
ans += makeWhiteOnce(cube);
}
return ans;
}
bool checkMid(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][1][0] != cube[i][1][1] || cube[i][1][N - 1] != cube[i][1][1])return false;
}
return true;
}
string makeMidOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
string t;
t += cube[0][N - 1][1];
t += cube[4][0][1];
if (t[0] != 'Y' && t[1] != 'Y') {
while (cube[4][0][1] != cube[4][1][1]) {
AnsAdd("z");
AnsAdd("U'");
}
if (t == "BR" || t == "RG" || t == "GO" || t == "OB") {
F4;
}
else {
F5;
}
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][1][0] != cube[4][1][1]) {
F4;
}
else if (cube[4][1][N - 1] != cube[4][1][1]) {
F5;
}
}
return ans;
}
string makeMid(vector<vector<vector<char>>>& cube)
{
string ans = makeDir(cube) + " ";
ans += makeUUUU(cube);
AnsAdd("y");
AnsAdd("y");
//从此,白色在下面,不能再调用makeDir和makeUUUU!!!!
while (true) {
if (checkMid(cube))break;
ans += makeMidOnce(cube);
}
return ans;
}
bool checkTopCross(const vector<vector<vector<char>>>& cube)
{
int num = 0;
if (cube[0][0][1] == 'Y')num++;
if (cube[0][N - 1][1] == 'Y')num++;
if (cube[0][1][0] == 'Y')num++;
if (cube[0][1][N - 1] == 'Y')num++;
return num == 4;
}
string makeTopCrossOnce(vector<vector<vector<char>>>& cube)
{
string ans;
int num = 0;
if (cube[0][0][1] == 'Y')num++;
if (cube[0][N - 1][1] == 'Y')num++;
if (cube[0][1][0] == 'Y')num++;
if (cube[0][1][N - 1] == 'Y')num++;
if (num == 2) {
while (cube[0][1][0] != 'Y') {
AnsAdd("U");
}
if(cube[0][N-1][1] == 'Y') {
AnsAdd("U");
}
}
F6;
return ans;
}
string makeTopCross(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCross(cube)) {
ans += makeTopCrossOnce(cube);
}
return ans;
}
bool checkTopDir(const vector<vector<vector<char>>>& cube)
{
int num = 0;
if (cube[0][0][0] == 'Y') num++;
if (cube[0][0][N - 1] == 'Y') num++;
if (cube[0][N - 1][0] == 'Y') num++;
if (cube[0][N - 1][N - 1] == 'Y') num++;
return num == 4;
}
string makeTopDirOnce(vector<vector<vector<char>>>& cube)
{
string ans;
int num = 0;
if(cube[0][0][0] == 'Y') num++;
if(cube[0][0][N - 1] == 'Y') num++;
if(cube[0][N - 1][0] == 'Y') num++;
if(cube[0][N - 1][N - 1] == 'Y') num++;
if (num == 0) {
while (cube[2][0][0] != 'Y') {
AnsAdd("U");
}
F7;
return ans;
}
if (num == 2) {
while (cube[5][0][N-1] != 'Y') {
AnsAdd("U");
}
F7;
return ans;
}
while (cube[0][0][0] != 'Y') {
AnsAdd("U");
}
if (cube[4][0][0] == 'Y') {
F7;
return ans;
}
F8;
return ans;
}
string makeTopDir(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopDir(cube)) {
ans += makeTopDirOnce(cube);
}
return ans;
}
bool checkTopCornerLoc(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][N-1])return false;
}
return true;
}
string makeTopCornerLocOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[3][0][0] == cube[3][0][N - 1])break;
}
F9;
return ans;
}
string makeTopCornerLoc(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCornerLoc(cube)) {
ans += makeTopCornerLocOnce(cube);
}
return ans;
}
bool checkTopEdgeLoc(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][1])return false;
}
return true;
}
string makeTopEdgeLocOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[4][0][0] == cube[4][0][1])break;
}
F7;
AnsAdd("z");
AnsAdd("z");
F8;
return ans;
}
string makeTopEdgeLoc(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopEdgeLoc(cube)) {
ans += makeTopEdgeLocOnce(cube);
}
return ans;
}
string makeAll(vector<vector<vector<char>>>& cube)
{
string ans;
while (cube[4][0][0] != cube[4][1][0]) {
AnsAdd("U");
}
while (cube[4][N-1][0] != cube[4][1][0]) {
AnsAdd("D");
}
return ans;
}
string autoRunOpts(vector<vector<vector<char>>>& cube)
{
string ans = makeAllCenter(cube) ; //中心大正方形合并
ans += makeDir(cube); //朝向
ans += makeAllEdge(cube) ; //棱块合并
ans += makeWhiteCross(cube) ; //白色十字
ans += makeWhite(cube) ;//白色
ans += makeMid(cube) ;//中间层
ans += makeTopCross(cube);//顶层十字
ans += makeTopDir(cube) ;//顶层朝向
ans += makeTopCornerLoc(cube); //角块归位
ans += makeTopEdgeLoc(cube);//棱块归位
ans += makeAll(cube);//复原
return ans;
}
void atuoRun(vector<string>& lines)
{
vector<vector<vector<char>>>cube;
for (int i = 0; i < 6; i++) {
string s = lines[i].substr(3, lines[i].length() - 3);
vector<vector<char>>v(N, vector<char>(N));
for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)v[i][j] = s[i * N + j];
cube.push_back(v);
}
string ans = autoRunOpts(cube);
std::ofstream outFile("D:/cubeOutput.txt", std::ios::app);
if (outFile.is_open()) {
outFile << ans << "\n";
outFile.close();
}
}
// 读取文件的所有行,每一行存入一个 string
std::vector<std::string> readAllLines(const std::string& path) {
std::vector<std::string> lines;
std::ifstream in(path);
if (!in.is_open()) {
return lines; // 打开失败,返回空
}
std::string line;
while (std::getline(in, line)) {
lines.push_back(line); // 每行一个 string 对象
}
return lines;
}
// 判断文件内容是否不为空
bool fileHasContent(const std::string& path) {
std::error_code ec;
// 1. 文件必须存在
if (!fs::exists(path, ec) || ec) {
return false;
}
// 2. 文件大小必须大于 0
if (fs::file_size(path, ec) == 0 || ec) {
return false;
}
return true;
}
void run1() // 自动填写操作序列
{
const std::string filePath = "D:/cubeInput.txt";
while (true) {
if (fileHasContent(filePath)) {
// 内容不为空,读取所有行
std::vector<std::string> lines = readAllLines(filePath);
atuoRun(lines);
std::ofstream clear(filePath, std::ios::trunc);
}
// 每隔 500ms 检查一次,避免忙等占用 CPU
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
int main()
{
N = 3;
// test1() //输入所有操作,只显示最终结果
// test2() //每次输入1个操作,实时显示结果
run1(); // 自动填写操作序列
return 0;
}
run1就是支持自动复原的接口,只要程序启动就行,后面就不用管了,所有操作都在网页端。
对于三阶魔方,这个代码已经完整了,只要点击一次网页上的自动运行,即可直接复原。

【完整操作序列】 F B R D B D' F B' L F L' U' D B' F' R F' R D F' R F B R B z z z z z z z z U D U U U U U' F' U' R z z z z U U D D U U U U U' F F z z z z U D U U U U U U F' U' R z z z z U U U D D D D z z z z U F z z z z U U U D D D D U U U U U U F' U' R z z z z U U U D D D D z z z U U F z z z z U U U D D D D U U U U U' F' U' R z z z z U U D D D D z z z U U F z z z z U U U D D D D U U U U F' U' R z z z z U U U U U U D D D D z z z U F z z z z U U U U U U U U D D D D U U U U U U U U F' U' R z z z z U z z z z D U U U U y' F R F' y z z z z D U U U U D U U U U D U U U U D U U U U U y' F R F' y z z z z D U U U D U U U U D U U U U U U R' D R z z z z D U U D U U U U U U y' F R F' y z z z z z z z z U U y y U U z U' z U' U' L' U L U F U' F' U U z U' z U' z U' U' L' U L U F U' F' U U z U' z U' z U' U' L' U L U F U' F' U U z U' z U' z U' U' L' U L U F U' F' U F R U R' U' F' F R U R' U' F' U R' U' R U' R' U U R U R R F F R' B' R F F R' B R' U U R' U' R U' R' U U R z z F U F' U F U U F' U U U D
校验:

校验通过。
6,操作序列化简
通过简单的化简,能稍微降低一些操作步数
std::string replaceStr(std::string str, const std::string& from,const std::string& to)
{
size_t pos = 0;
if ((pos = str.find(from, pos)) != std::string::npos) {
str.replace(pos, from.length(), to);
}
return str;
}
string replaceAns(string ans)
{
for (char c : {'U', 'D', 'L', 'R', 'F', 'B', 'x', 'y', 'z'})
{
string s1 = "";
s1 += c;
s1 += "' ";
s1 += c;
s1 += " ";
string s2 = " ";
ans = replaceStr(ans, s1 ,s2);
s1 = "";
s1 += c;
s1 += " ";
s1 += c;
s1 += "' ";
ans = replaceStr(ans, s1, s2);
s1 = "";
s1 += c;
s1 += " ";
s1 += c;
s1 += " ";
s1 += c;
s1 += " ";
s2 = "";
s2 += c;
s2 += "' ";
ans = replaceStr(ans, s1, s2);
s1 = "";
s1 += c;
s1 += "' ";
s1 += c;
s1 += "' ";
s1 += c;
s1 += "' ";
s2 = "";
s2 += c;
s2 += " ";
ans = replaceStr(ans, s1, s2);
s1 = " ";
s2 = " ";
ans = replaceStr(ans, s1, s2);
s1 = " ";
ans = replaceStr(ans, s1, s2);
s1 = " ";
ans = replaceStr(ans, s1, s2);
}
return ans;
}
void atuoRun(vector<string>& lines)
{
vector<vector<vector<char>>>cube;
for (int i = 0; i < 6; i++) {
string s = lines[i].substr(3, lines[i].length() - 3);
vector<vector<char>>v(N, vector<char>(N));
for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)v[i][j] = s[i * N + j];
cube.push_back(v);
}
string ans = autoRunOpts(cube);
for(int i=0;i<10000;i++)ans = replaceAns(ans);
std::ofstream outFile("D:/cubeOutput.txt", std::ios::app);
if (outFile.is_open()) {
outFile << ans << "\n";
outFile.close();
}
}
这样,完整的复原过程就从300-400步化简到了150-200步(x y z操作不计入步数)
【完整操作序列】 L B' F D' R' L' D R F' R' U R B F U B' F' R' D' R L R' D' L' F D D F' U' R F' U' R U D' U' F' U' R U F' U' R U U z' U' F U' F' U' R z' U' F U' F' U' R z' U' F U U F' U' R U z' U' U' R U z F F U U F F U U F F U' D U y' F R F' y D U' D y' F R' F' y D D y' F R F' y D D U' y' F R F' y D U D' U U y' F R F' y U U y y U z R U' R' U' F' U F U U z R U' R' U' F' U F U' z U' z R U' R' U' F' U F U' F R U R' U' R U R' U' F' U R' U' R U' R' U U R U' R' U' R U' R' U U R U' R R F F R' B' R F F R' B R' R' U' R U' R' U U R z z F U F' U F U U F' U' D
六,操作集扩充
前面的二阶和三阶都是18种操作,即6+6*2=18,只涉及单层操作。
这里我们改成支持多层操作,N阶魔方有f(N) = 6+6*2*(N-1)种操作.
f(2)=18,f(3)=30,f(4)=42......
当然,三阶魔方的相关代码不用再改了,代码更新之后只用于N>3的情况。
为了兼容,以四阶魔方为例,我们把R方向的操作命名成R、R2、R3,把R'方向的操作命名成R'、R2'、R3'
七,四阶魔方
1,网页版程序
参考 四阶魔方 网页版
2,交换2个棱块
为了充分验证我提出的偶数阶魔方的状态恒等式,这里我采用阶段二算法。(如果用阶段三算法,就不用搞这些逆序运算了)
关于解决状态恒等式的三阶段,参考《魔方复原方法推导》
这里有2个编码技巧,第一就是用二次编码,就不需要自己一个个对颜色,第二就是用rotate,就不需要自己一个个算坐标。
首先运行:
#define showOneEdge cout << cube[4][0][id] << " " << cube[0][N - 1][id] << " ";
void test3(vector<vector<vector<char>>>& cube)
{
int id = 1;
showOneEdge;
rotate(cube, "U");
showOneEdge;
rotate(cube, "U");
showOneEdge;
rotate(cube, "U");
showOneEdge;
rotate(cube, "x");
rotate(cube, "x");
showOneEdge;
rotate(cube, "U");
showOneEdge;
rotate(cube, "U");
showOneEdge;
rotate(cube, "U");
showOneEdge;
rotate(cube, "F");
showOneEdge;
rotate(cube, "F");
rotate(cube, "F");
showOneEdge;
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "F");
showOneEdge;
rotate(cube, "F");
rotate(cube, "F");
showOneEdge;
}
输入复原状态下的魔方,输出:
RW,BW,OW,GW,OY,BY,RY,GY,OG,OB,RB,RG,
这样就得到了对24个棱块进行编码的代码了:
int getId(char a, char b)
{
vector<string> v{"RW", "BW", "OW", "GW", "OY", "BY", "RY", "GY", "OG", "OB", "RB", "RG"};
for (int i = 0; i < 12; i++) {
if (v[i][0] == a && v[i][1] == b)return i;
}
return getId(b, a) + 12;
}
然后再复用上面的代码,变成采集24个棱块的代码:
#define GetTwoEdgeId v.push_back(getId(cube[4][0][id], cube[0][N - 1][id]));v.push_back(getId(cube[0][N - 1][N - 1 - id], cube[4][0][N - 1 - id]));
bool checkEdgeLocStatus(vector<vector<vector<char>>> cube,int id) //check***系列函数中,少有的非const&的cube参数,这里不要用&
{
vector<int>v;
GetTwoEdgeId;
rotate(cube, "U");
GetTwoEdgeId;
rotate(cube, "U");
GetTwoEdgeId;
rotate(cube, "U");
GetTwoEdgeId;
rotate(cube, "x");
rotate(cube, "x");
GetTwoEdgeId;
rotate(cube, "U");
GetTwoEdgeId;
rotate(cube, "U");
GetTwoEdgeId;
rotate(cube, "U");
GetTwoEdgeId;
rotate(cube, "F");
GetTwoEdgeId;
rotate(cube, "F");
rotate(cube, "F");
GetTwoEdgeId;
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "F");
GetTwoEdgeId;
rotate(cube, "F");
rotate(cube, "F");
GetTwoEdgeId;
return true;//// 待更新
}
复原状态的魔方,v一定是0 12 1 13 2 14 3 15 4 16 5 17 6 18 7 19 8 20 9 21 10 22 11 23,逆序数是158
3,U位R位棱组交叉
对于四阶魔方,每次至少合并1个棱组,最后一定会小于3个待合并棱组,此时要么已完成,要么就是:

为了方便理解代码,我们把这种情况称为U位R位棱组交叉。
判断“U位R位棱组交叉”的方法:首先让正面U位棱组mid处和正面R位棱组id处棱块属于同一棱组,且方向一致,如上图的红黄棱块,此时,如果U位id处和R位mid处属于同一棱组,那就是U位R位棱组交叉。
4,自动复原
#include <iostream>
#include <string_view>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <array>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <iomanip>
#include <cmath>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
#include <thread>
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
class SingleVectorOpt
{
public:
//翻转vector、翻转二维vector的每一行
template<typename T>
static vector<T> frev(const vector<T>& v)
{
vector<T> ans;
ans.resize(v.size());
for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
return ans;
}
template<typename T>
static vector<vector<T>> frev(const vector<vector<T>>& v)
{
vector<vector<T>>ans;
for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
return ans;
}
//沿主对角线(左上角到右下角)翻转二维vector
template<typename T>
static vector<vector<T>> foverturn(const vector<vector<T>>& v)
{
vector<vector<T>> ans(v[0].size());
for (int i = 0; i < v[0].size(); i++) {
ans[i].resize(v.size());
for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
}
return ans;
}
//顺时针旋转二维vector
template<typename T>
static vector<vector<T>> frotation(const vector<vector<T>>& v)
{
return frev(foverturn(v));
}
//从vector(一维或2维)中删除所有的x
template<typename T>
static void deletAllX(vector<T>& v, T x)
{
for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
}
template<typename T>
static void deletAllX(vector<vector<T>>& v, T x)
{
for (auto& vi : v)deletAllX(vi, x);
}
// 去掉相邻重复元素
template<typename T>
static void deleteNeiborSame(vector<T>& v)
{
v.erase(std::unique(v.begin(), v.end()), v.end());
}
//判断数组去掉相邻重复数之后有多少个不同的数
template<typename T>
static int getDifNum(const vector<T>& v)
{
auto v2 = v;
deleteNeiborSame(v2);
return v2.size();
}
//vector乘一个数
template<typename T1, typename T2>
static void fcheng(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
}
//vector加一个数
template<typename T1, typename T2>
static void fjia(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
}
//二维数组每一行排序
template<typename T>
static void sortEveryLine(vector<vector<T>>& v)
{
for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
}
//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
template<typename T, class P>
static inline vector<int>firstInLeft(vector<T>v, P pr)
{
vector<int> ans;
if (v.size() == 0)return ans;
stack<T>st;
st.push(0);
ans.push_back(-1);
for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
{
while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
if (st.empty())ans.push_back(-1);
else ans.push_back(st.top());
st.push(i);
}
return ans;
}
//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fminlef(vector<T> v)
{
return firstInLeft(v, [](T a, T b) {return a < b; }); //可换为自定义函数
}
//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fminlef2(vector<T> v)
{
return firstInLeft(v, [](T a, T b) {return a <= b; }); //可换为自定义函数
}
//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fmaxlef(vector<T> v)
{
fcheng(v, -1);
vector<int>ans = fminlef(v);
return ans;
}
//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fmaxlef2(vector<T> v)
{
fcheng(v, -1);
vector<int>ans = fminlef2(v);
return ans;
}
//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fminrig(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fminlef(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fminrig2(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fminlef2(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fmaxrig(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fmaxlef(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fmaxrig2(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
static map<int, map<int, int>> splitAtHalf(vector<int>& v)
{
vector<int>s;
int n = 0;
s.push_back(n);
for (auto x : v) {
n += x;
s.push_back(n);
}
map<int, map<int, int>>ans;
for (int i = 0; i < v.size(); i++) {
int id = i;
for (int j = i; j < v.size(); j++) {
while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
ans[i][j] = id;
}
}
return ans;
}
//获取所有的众数
template<typename T>
static vector<T> getMost(const vector<T>& v)
{
int n = 0;
map<T, int>m;
for (auto x : v)n = max(n, ++m[x]);
vector<T>ans;
for (auto p : m)if (p.second == n)ans.push_back(p.first);
return ans;
}
};
#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行
int N;
vector<vector<vector<char>>> Init()
{
vector<vector<vector<char>>> ans;
for (auto c : { 'W','Y','G','B','R','O' }) //上下左右前后
{
vector<char> temp(N, c);
vector<vector<char>>v(N, temp);
ans.push_back(v);
}
return ans;
}
void show(vector<vector<vector<char>>>& cube)
{
cout << endl << "U: ";
for (auto v : cube[0])for (auto ch : v)cout << ch;
cout << endl << "D: ";
for (auto v : cube[1])for (auto ch : v)cout << ch;
cout << endl << "L: ";
for (auto v : cube[2])for (auto ch : v)cout << ch;
cout << endl << "R: ";
for (auto v : cube[3])for (auto ch : v)cout << ch;
cout << endl << "F: ";
for (auto v : cube[4])for (auto ch : v)cout << ch;
cout << endl << "B: ";
for (auto v : cube[5])for (auto ch : v)cout << ch;
cout << endl;
}
void rotate(vector<vector<vector<char>>>& cube, string s);
void rotate2(vector<vector<vector<char>>>& cube, string s)
{
if (s.length() == 1)s += "1";
if (s[0] == 'U')
{
cube[0] = Frotation(cube[0]);
for (int i = 0; i < s[1] - '0'; i++) {
auto v = cube[2][i];
cube[2][i] = cube[4][i], cube[4][i] = cube[3][i], cube[3][i] = cube[5][i], cube[5][i] = v;
}
return;
}
string s2 = "U";
if (s[0] == 'D') {
rotate(cube, "x");
rotate(cube, "x");
rotate(cube, s2 + s[1]);
rotate(cube, "x");
rotate(cube, "x");
return;
}
if (s[0] == 'R')
{
rotate(cube, "y'");
rotate(cube, s2 + s[1]);
rotate(cube, "y");
return;
}
if (s[0] == 'L')
{
rotate(cube, "y");
rotate(cube, s2 + s[1]);
rotate(cube, "y'");
return;
}
if (s[0] == 'F')
{
rotate(cube, "x");
rotate(cube, s2 + s[1]);
rotate(cube, "x'");
return;
}
if (s[0] == 'B')
{
rotate(cube, "x'");
rotate(cube, s2 + s[1]);
rotate(cube, "x");
return;
}
}
void rotate(vector<vector<vector<char>>>& cube, string s)
{
int len = s.length();
if (s[len - 1] == '\'') {
string s2 = s.substr(0, len - 1);
rotate(cube, s2);
rotate(cube, s2);
rotate(cube, s2);
return;
}
if (s == "x")
{
cube[3] = Frotation(cube[3]);
cube[2] = Frotation(Frotation(Frotation(cube[2])));
auto v = cube[0];
cube[0] = cube[4];
cube[4] = Frev<vector<char>>(cube[1]); //上下翻转
cube[1] = Frev<char>(cube[5]); //翻转每一行
cube[5] = Frev<char>(Frev<vector<char>>(v));
return;
}
if (s == "z") {
cube[0] = Frotation(cube[0]);
cube[1] = Frotation(cube[1]);
auto v = cube[2];
cube[2] = cube[4], cube[4] = cube[3], cube[3] = cube[5], cube[5] = v;
return;
}
if (s == "y") {
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "x");
rotate(cube, "z");
return;
}
rotate2(cube, s);
}
void test1() //输入所有操作,只显示最终结果
{
vector<string>opts;
string c;
while (cin >> c)opts.push_back(c);
auto cube = Init();
for (auto c : opts) {
rotate(cube, c);
}
show(cube);
}
void test2() //每次输入1个操作,实时显示结果
{
auto cube = Init();
string c;
while (cin >> c) {
rotate(cube, c);
show(cube);
cout << endl;
}
}
string makeOpt(const string& opt, int num)
{
if (num == 1)return opt;
string s1 = opt;
string s2 = std::to_string(num);
if (s1.length() == 1)return s1 + s2; //不带'
//带'
string s3, s4;
s3 += s1[0], s4 += s1[1];
return s3 + s2 + s4;
}
#define AnsAdd(s) ans += s;ans += " "; rotate(cube, s);
// F1-F9 是三阶魔方的公式
#define F1 AnsAdd("y'");AnsAdd("F");AnsAdd("R'");AnsAdd("F'");AnsAdd("y");AnsAdd("D");AnsAdd("D");AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块1 y' F R' F' y D D y' F R F' y
#define F2 AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块2 y' F R F' y
#define F3 AnsAdd("R'");AnsAdd("D");AnsAdd("R");// 白色角块3 R' D' R
#define F4 AnsAdd("U'");AnsAdd("L'");AnsAdd("U");AnsAdd("L");AnsAdd("U");AnsAdd("F");AnsAdd("U'");AnsAdd("F'");// 中层棱块1 U' L' U L U F U' F'
#define F5 AnsAdd("U");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");AnsAdd("U");AnsAdd("F");// 中层棱块2 U R U' R' U' F' U F
#define F6 AnsAdd("F");AnsAdd("R");AnsAdd("U");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");// 顶层十字 F R U R' U' F'
#define F7 AnsAdd("R'");AnsAdd("U'");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U");AnsAdd("U");AnsAdd("R"); // 小鱼1 R' U' R U' R' U U R
#define F8 AnsAdd("F");AnsAdd("U");AnsAdd("F'");AnsAdd("U");AnsAdd("F");AnsAdd("U");AnsAdd("U");AnsAdd("F'"); // 小鱼2 F U F' U F U U F'
#define F9 AnsAdd("R");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B'");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B");AnsAdd("R'"); // 换角 R R F F R' B' R F F R' B R'
//F10 单棱对换 R2 U U R2 U U R2' x' L2' U U L2 x' U U R2 U U R2'
#define F10_1(id) AnsAdd(makeOpt("R",id+1));AnsAdd(makeOpt("R'",id)); //R2
#define F10_2(id) AnsAdd(makeOpt("R'",id+1));AnsAdd(makeOpt("R",id)); //R2'
#define F10_3 AnsAdd("U");AnsAdd("U"); //U U
#define F10_4(id) F10_3;F10_1(id);F10_3;F10_2(id); //U U R2 U U R2'
#define F10(id) F10_1(id);F10_4(id);AnsAdd("x'");AnsAdd(makeOpt("L'",id+1));AnsAdd(makeOpt("L",id));F10_3;\
AnsAdd(makeOpt("L",id+1));AnsAdd(makeOpt("L'",id));AnsAdd("x'");F10_4(id);
//F11 U位棱组翻转
#define F11 AnsAdd("U");AnsAdd("U");AnsAdd("B");AnsAdd("L");AnsAdd("U'");
//F12 棱块合并
#define F12 AnsAdd("F2'"); AnsAdd("F"); AnsAdd("R"); AnsAdd("U'"); AnsAdd("R'"); AnsAdd("U"); AnsAdd("F2");AnsAdd("F'");
//F13 双棱对换
#define F13_1 F10_3;AnsAdd("F");AnsAdd("F");
#define F13_2 AnsAdd("R2");F10_3;AnsAdd("R2'");
#define F13_3 F13_2;F13_1;F13_1;F13_1;F13_2;
#define F13 F13_3;AnsAdd("x'");F13_3;AnsAdd("x'");F13_3;
string makeDir(vector<vector<vector<char>>>& cube) //调整白色面朝上
{
string ans;
int id = N / 2;
if (cube[1][id][id] == 'W') {
AnsAdd("x");
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][id][id] == 'W')break;
}
if (cube[0][id][id] != 'W') {
AnsAdd("x");
}
return ans;
}
bool checkTopCenter(const vector<vector<vector<char>>>& cube, char c)
{
for (int j = 1; j < N - 1; j++) {
for (int k = 1; k < N - 1; k++) {
if (cube[0][j][k] != c) {
return false;
}
}
}
return true;
}
string makeCenter4OnceTry(vector<vector<vector<char>>>& cube, char c)
{
string ans;
for (int i = 0; i < 4; i++) {
bool flag = false;
for (int j = 1; j < N - 1; j++) {
for (int k = 1; k < N - 1; k++) {
if (cube[4][j][k] == c) {
flag = true;
break;
}
}
if (flag)break;
}
if (!flag) {
AnsAdd("z");
continue;
}
while (cube[0][1][N - 2] == c) {
AnsAdd("U");
}
while (cube[4][N - 2][1] != c) {
AnsAdd("F");
}
AnsAdd("R2'");
AnsAdd("F'");
AnsAdd("R2");
return ans;
}
return "";
}
string makeCenter4Once(vector<vector<vector<char>>>& cube, char c)
{
string ans = makeCenter4OnceTry(cube, c);
if (!ans.empty())return ans;
AnsAdd("x");
ans += makeCenter4OnceTry(cube, c);
AnsAdd("x'");
return ans;
}
string makeCenterWhiteOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("z");
int j, k;
bool flag = false;
for (j = 1; j < N - 1; j++) {
for (k = 1; k < N - 1; k++) {
if (cube[4][j][k] == 'W') {
flag = true;
break;
}
}
if (flag)break;
}
if (!flag)continue;
while (cube[0][j][k] == 'W') {
AnsAdd("U");
}
AnsAdd(makeOpt("B", j));
AnsAdd(makeOpt("F'", N - 1 - j));
AnsAdd("F");
AnsAdd(makeOpt("R", N - k));
AnsAdd(makeOpt("R'", N - 1 - k));
AnsAdd(makeOpt("F", N - 1 - j));
AnsAdd(makeOpt("B'", j));
return ans;
}
AnsAdd("x");
return "z"; //// 待更新"
}
string makeCenterWhite(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCenter(cube, 'W')) {
ans += makeCenter4Once(cube, 'W'); //N>4时要切换到makeCenterWhiteOnce,目前还没写完这个函数
}
return ans;
}
string makeCenterYellowOnce(vector<vector<vector<char>>>& cube)
{
return "";///待更新
}
string makeCenterYellow(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCenter(cube, 'Y')) {
ans += makeCenter4Once(cube, 'Y'); //N>4时要切换到makeCenterYellowOnce,目前还没写完这个函数
}
return ans;
}
string makeCenterRedOnce(vector<vector<vector<char>>>& cube)
{
return "";///待更新
}
string makeCenterRed(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCenter(cube, 'R')) {
ans += makeCenter4Once(cube, 'R'); //N>4时要切换到makeCenterRedOnce,目前还没写完这个函数
}
return ans;
}
string makeCenterGreenOnce(vector<vector<vector<char>>>& cube)
{
return "";///待更新
}
string makeCenterGreen(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCenter(cube, 'G')) {
ans += makeCenter4Once(cube, 'G'); //N>4时要切换到makeCenterGreenOnce,目前还没写完这个函数
}
return ans;
}
string makeCenterOrangeOnce(vector<vector<vector<char>>>& cube)
{
return "";///待更新
}
string makeCenterOrange(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCenter(cube, 'O')) {
ans += makeCenter4Once(cube, 'O'); //N>4时要切换到makeCenterOrangeOnce,目前还没写完这个函数
}
return ans;
}
string makeAllCenter(vector<vector<vector<char>>>& cube)
{
string ans = makeDir(cube);
ans += makeCenterWhite(cube);
AnsAdd("x");
AnsAdd("x");
ans += makeCenterYellow(cube);
AnsAdd("x");
AnsAdd("x");
//上白下黄
for (int i = 0; i < 4; i++) {
if (cube[4][N / 2][N / 2] == 'R')break;
AnsAdd("z");
}
//上白下黄 前红
AnsAdd("x");
AnsAdd("z'");
//上红 左白 右黄
ans += makeCenterRed(cube);
ans += makeDir(cube);
for (int i = 0; i < 4; i++) {
if (cube[4][N / 2][N / 2] == 'R')break;
AnsAdd("z");
}
//上白下黄 前红
AnsAdd("z");
AnsAdd("z");
AnsAdd("y'");
//上绿 左白 右黄
ans += makeCenterGreen(cube);
ans += makeDir(cube);
for (int i = 0; i < 4; i++) {
if (cube[4][N / 2][N / 2] == 'R')break;
AnsAdd("z");
}
//上白下黄 前红
AnsAdd("z");
AnsAdd("y'");
//上橙 左白 右黄
ans += makeCenterOrange(cube);
return ans;
}
int getId(char a, char b)
{
vector<string> v{ "RW", "BW", "OW", "GW", "OY", "BY", "RY", "GY", "OG", "OB", "RB", "RG" };
for (int i = 0; i < 12; i++) {
if (v[i][0] == a && v[i][1] == b)return i;
}
return getId(b, a) + 12;
}
template<typename T>
int getInvertNum(vector<T>v)
{
int n = 0;
for (int i = 0; i < v.size(); i++) {
for (int j = i + 1; j < v.size(); j++) {
if (v[i] > v[j])n++;
}
}
return n;
}
#define ForEachEdgeUp(func) func;rotate(cube, "U");func;rotate(cube, "U");func;rotate(cube, "U");func;
#define ForEachEdgeLR(func) rotate(cube, "F");func;rotate(cube, "F");rotate(cube, "F");func;
// 依次把12个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdge(func) ForEachEdgeUp(func);rotate(cube, "x");rotate(cube, "x");ForEachEdgeUp(func);\
ForEachEdgeLR(func);rotate(cube, "z");rotate(cube, "z");ForEachEdgeLR(func);
#define GetTwoEdgeId v.push_back(getId(cube[4][0][id], cube[0][N - 1][id]));v.push_back(getId(cube[0][N - 1][N - 1 - id], cube[4][0][N - 1 - id]));
bool checkEdgeLocStatus(vector<vector<vector<char>>> cube, int id) //check***系列函数中,少有的非const&的cube参数,这里不要用&
{
vector<int>v;
ForEachEdge(GetTwoEdgeId);
return getInvertNum(v) % 2 == 0;
}
string makeEdgeLocStatus(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 1; i < N / 2; i++) {
if (!checkEdgeLocStatus(cube, i)) {
F10(i);//交换2个棱块
}
}
return ans;
}
#define ForEachEdgeUp2(func) func;AnsAdd("U");func;AnsAdd("U");func;AnsAdd("U");func;
#define ForEachEdgeLR2(func) AnsAdd("F");func;AnsAdd("F");AnsAdd("F");func;
// 依次把12个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdge2(func) ForEachEdgeUp2(func);AnsAdd( "x");AnsAdd( "x");ForEachEdgeUp2(func);\
ForEachEdgeLR2(func);AnsAdd( "z");AnsAdd( "z");ForEachEdgeLR2(func);
// 依次把10个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdgeExceptLR(func) ForEachEdgeUp2(func);AnsAdd( "B");AnsAdd( "U");AnsAdd( "B");AnsAdd( "U");AnsAdd( "B");AnsAdd( "U");\
AnsAdd( "D");AnsAdd( "B");AnsAdd( "B"); ForEachEdgeUp2(func);AnsAdd( "D");AnsAdd( "B");AnsAdd( "D");AnsAdd( "B");AnsAdd( "U");\
AnsAdd( "B");AnsAdd( "U");func;AnsAdd( "U");func;
#define case1 (cube[0][N - 1][mid] == target[0] && cube[4][0][mid] == target[1])
#define case2 (cube[0][N - 1][mid] == target[1] && cube[4][0][mid] == target[0])
#define case3 (cube[0][N - 1][id] == target[0] && cube[4][0][id] == target[1])
#define case4 (cube[0][N - 1][id] == target[1] && cube[4][0][id] == target[0])
#define FindEdgeWithTarget if (case1||case2||((N%2==0)&&(case3||case4)))goto here;
#define FindEdgeWithDif if (cube[0][N - 1][mid] != cube[0][N - 1][id] || cube[4][0][mid] !=cube[4][0][id])goto here2;
bool checkAllEdge(vector<vector<vector<char>>> &cube,int id, string &ans)//check***系列函数中,少有的非const&的cube参数,这里要用&
{
int mid = (N - 1) / 2;
ForEachEdge2(if (cube[4][0][id] != cube[4][0][mid] || cube[0][N - 1][id]!= cube[0][N - 1][mid])return false;)
return true;
}
string makeAllEdgeOnce(vector<vector<vector<char>>>& cube,int id)
{
string ans;
string target;
target += cube[0][N - 1][id];
target += cube[4][0][id];
int mid = (N - 1) / 2;
char c1 = cube[0][N - 1][mid], c2 = cube[4][0][mid];
AnsAdd("F");//棱组停留在正面R位
FindEdgeWithTarget;
AnsAdd("U");
AnsAdd("L");//一个不带mid的棱组停留在正面L位
ForEachEdgeExceptLR(FindEdgeWithTarget);
here:
//带mid的棱组停留在正面U位
if (N % 2 == 1 && cube[0][N - 1][mid] == target[1] && cube[4][0][mid] == target[0]) {
F11;
}
if (N % 2 == 0 && cube[0][N - 1][id] == target[1] && cube[4][0][id] == target[0]) {
F11;
}
//此时,正面U位棱组mid处和正面R位棱组id处棱块属于同一棱组,且方向一致
if (c1 == cube[0][N - 1][id] && c2 == cube[4][0][id]) {
// U位R位棱组交叉
F11;
AnsAdd("z'");
AnsAdd("x'");
F12; /////待更新 对于非4阶魔方,需要换公式
AnsAdd("R'");
AnsAdd("z'");
AnsAdd("x'");
AnsAdd("L'");
AnsAdd("B");
AnsAdd("D'");
F12; /////待更新 对于非4阶魔方,需要换公式
return ans;
}
AnsAdd("U");
AnsAdd("L");//带mid的棱组停留在正面L位
ForEachEdgeExceptLR(FindEdgeWithDif);
here2:
//带dif的棱组停留在正面U位
AnsAdd("R");
AnsAdd("R");
AnsAdd("B");
AnsAdd("U'");
AnsAdd("R");
AnsAdd("B");
AnsAdd("B");
AnsAdd("z");
AnsAdd("z");
AnsAdd("x'");
F12; /////待更新 对于非4阶魔方,需要换公式
return ans;
}
string makeAllEdge(vector<vector<vector<char>>>& cube)
{
string ans;
int mid = (N - 1) / 2;
for (int i = mid + 1; i < N - 1; i++) {
while (true) {
string s;
bool ret = checkAllEdge(cube, i, s);
ans += s;
if (ret) {
break;
}
ans += makeAllEdgeOnce(cube,i);
}
}
for (int i = 1; i < mid; i++) {
/////待更新 对于N>4涉及
}
return ans;
}
string makeUUUU(vector<vector<vector<char>>>& cube) //白色层方向回正
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][N - 1][1] == 'W' && cube[4][0][1] == 'R') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][1][N - 1] == 'W' && cube[3][0][1] == 'B') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][1][0] == 'W' && cube[2][0][1] == 'G') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][0][1] == 'W' && cube[5][0][1] == 'O') {
return ans;
}
}
return ans;
}
bool checkWhiteCross(const vector<vector<vector<char>>>& cube)// 检查白色十字是否完成
{
char whiteColor = 'W';
if (cube[0][0][1] != whiteColor || cube[0][N - 1][1] != whiteColor || cube[0][1][0] != whiteColor || cube[0][1][N - 1] != whiteColor) {
return false;
}
if (cube[2][0][1] != 'G' || cube[3][0][1] != 'B' || cube[4][0][1] != 'R') {
return false;
}
return true;
}
string makeWhiteCrossOnce(vector<vector<vector<char>>>& cube)
{
string ans = "";
for (int i = 0; i < 4; i++) {
AnsAdd("D");
if (cube[4][N - 1][1] == 'W') {
ans += makeUUUU(cube);
char c = cube[1][N - 1][1];
if (c == 'B') {
AnsAdd("U");
}
if (c == 'O') {
AnsAdd("U");
AnsAdd("U");
}
if (c == 'G') {
AnsAdd("U'");
}
AnsAdd("F'");
AnsAdd("U'");
AnsAdd("R");
return ans;
}
if (cube[1][N - 1][1] == 'W') {
ans += makeUUUU(cube);
char c = cube[4][N - 1][1];
if (c == 'B') {
AnsAdd("U");
}
if (c == 'O') {
AnsAdd("U");
AnsAdd("U");
}
if (c == 'G') {
AnsAdd("U'");
}
AnsAdd("F");
AnsAdd("F");
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][1][N - 1] == 'W' || cube[3][1][0] == 'W') {
while (cube[0][N - 1][1] == 'W') {
AnsAdd("U");
}
AnsAdd("F");
return ans;
}
}
ans += makeUUUU(cube);
string s = "BOGR";
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[0][N - 1][1] != 'W' || cube[4][0][1] != s[i]) {
AnsAdd("F");
AnsAdd("F");
return ans;
}
}
return ans;
}
string makeWhiteCross(vector<vector<vector<char>>>& cube)
{
string ans;
while (true) {
ans += makeDir(cube);
ans += makeUUUU(cube);
if (checkWhiteCross(cube))break;
ans += makeWhiteCrossOnce(cube);
}
return ans;
}
bool checkWhite(const vector<vector<vector<char>>>& cube)// 检查白色是否完成
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][1] || cube[i][0][N - 1] != cube[i][0][1])return false;
}
return true;
}
string makeWhiteOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("D");
ans += makeUUUU(cube);
string t;
t += cube[1][N - 1][N - 1];
t += cube[3][N - 1][0];
t += cube[4][N - 1][N - 1];
sort(t.begin(), t.end());
if (t == "BOW") {
AnsAdd("U");
}
if (t == "GOW") {
AnsAdd("U");
AnsAdd("U");
}
if (t == "GRW") {
AnsAdd("U");
AnsAdd("U");
AnsAdd("U");
}
if (cube[1][N - 1][N - 1] == 'W') {
F1;
return ans;
}
if (cube[4][N - 1][N - 1] == 'W') {
F2;
return ans;
}
if (cube[3][N - 1][0] == 'W') {
F3;
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[4][0][N - 1] != cube[4][0][1] || cube[3][0][0] != cube[3][0][1]) {
F2;
return ans;
}
}
return ans;
}
string makeWhite(vector<vector<vector<char>>>& cube)
{
string ans;
while (true) {
ans += makeDir(cube);
if (checkWhite(cube))break;
ans += makeWhiteOnce(cube);
}
return ans;
}
bool checkMid(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][1][0] != cube[i][1][1] || cube[i][1][N - 1] != cube[i][1][1])return false;
}
return true;
}
string makeMidOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
string t;
t += cube[0][N - 1][1];
t += cube[4][0][1];
if (t[0] != 'Y' && t[1] != 'Y') {
while (cube[4][0][1] != cube[4][1][1]) {
AnsAdd("z");
AnsAdd("U'");
}
if (t == "BR" || t == "RG" || t == "GO" || t == "OB") {
F4;
}
else {
F5;
}
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][1][0] != cube[4][1][1]) {
F4;
}
else if (cube[4][1][N - 1] != cube[4][1][1]) {
F5;
}
}
return ans;
}
string makeMid(vector<vector<vector<char>>>& cube)
{
string ans = makeDir(cube) + " ";
ans += makeUUUU(cube);
AnsAdd("y");
AnsAdd("y");
//从此,白色在下面,不能再调用makeDir和makeUUUU!!!!
while (true) {
if (checkMid(cube))break;
ans += makeMidOnce(cube);
}
return ans;
}
bool checkTopCross(const vector<vector<vector<char>>>& cube)
{
int num = 0;
if (cube[0][0][1] == 'Y')num++;
if (cube[0][N - 1][1] == 'Y')num++;
if (cube[0][1][0] == 'Y')num++;
if (cube[0][1][N - 1] == 'Y')num++;
return num == 4;
}
string makeTopCrossOnce(vector<vector<vector<char>>>& cube)
{
string ans;
int num = 0;
if (cube[0][0][1] == 'Y')num++;
if (cube[0][N - 1][1] == 'Y')num++;
if (cube[0][1][0] == 'Y')num++;
if (cube[0][1][N - 1] == 'Y')num++;
if (num == 2) {
while (cube[0][1][0] != 'Y') {
AnsAdd("U");
}
if (cube[0][N - 1][1] == 'Y') {
AnsAdd("U");
}
}
F6;
return ans;
}
string makeTopCross(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCross(cube)) {
ans += makeTopCrossOnce(cube);
}
return ans;
}
bool checkTopDir(const vector<vector<vector<char>>>& cube)
{
int num = 0;
if (cube[0][0][0] == 'Y') num++;
if (cube[0][0][N - 1] == 'Y') num++;
if (cube[0][N - 1][0] == 'Y') num++;
if (cube[0][N - 1][N - 1] == 'Y') num++;
return num == 4;
}
string makeTopDirOnce(vector<vector<vector<char>>>& cube)
{
string ans;
int num = 0;
if (cube[0][0][0] == 'Y') num++;
if (cube[0][0][N - 1] == 'Y') num++;
if (cube[0][N - 1][0] == 'Y') num++;
if (cube[0][N - 1][N - 1] == 'Y') num++;
if (num == 0) {
while (cube[2][0][0] != 'Y') {
AnsAdd("U");
}
F7;
return ans;
}
if (num == 2) {
while (cube[5][0][N - 1] != 'Y') {
AnsAdd("U");
}
F7;
return ans;
}
while (cube[0][0][0] != 'Y') {
AnsAdd("U");
}
if (cube[4][0][0] == 'Y') {
F7;
return ans;
}
F8;
return ans;
}
string makeTopDir(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopDir(cube)) {
ans += makeTopDirOnce(cube);
}
return ans;
}
bool checkTopCornerLoc(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][N - 1])return false;
}
return true;
}
string makeTopCornerLocOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[3][0][0] == cube[3][0][N - 1])break;
}
F9;
return ans;
}
string makeTopCornerLoc(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCornerLoc(cube)) {
ans += makeTopCornerLocOnce(cube);
}
return ans;
}
string makeChangeEdge(vector<vector<vector<char>>>& cube, bool &changed)
{
string ans;
changed = false;
//方向回正
while (cube[4][1][1] != 'O') {
AnsAdd("z");
}
while (cube[4][0][0] != cube[4][1][0]) {
AnsAdd("U");
}
vector<char>v;
for (int i = 2; i <= 5; i++) {
v.push_back(cube[i][0][1]);
}
// 复原是GBOR
if (getInvertNum(v) % 2 == 0) {
F13;
changed = true;
}
return ans;
}
bool checkTopEdgeLoc(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][1])return false;
}
return true;
}
string makeTopEdgeLocOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[4][0][0] == cube[4][0][1])break;
}
F7;
AnsAdd("z");
AnsAdd("z");
F8;
return ans;
}
string makeTopEdgeLoc(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopEdgeLoc(cube)) {
ans += makeTopEdgeLocOnce(cube);
}
return ans;
}
string makeAll(vector<vector<vector<char>>>& cube)
{
string ans;
while (cube[4][0][0] != cube[4][1][0]) {
AnsAdd("U");
}
while (cube[4][N - 1][0] != cube[4][1][0]) {
AnsAdd("D");
}
return ans;
}
string autoRunOpts(vector<vector<vector<char>>>& cube)
{
string ans = makeAllCenter(cube); //中心大正方形合并
ans += makeEdgeLocStatus(cube); //棱块位置奇偶性
ans += makeAllEdge(cube); //棱块合并
ans += makeWhiteCross(cube); //白色十字
ans += makeWhite(cube);//白色
ans += makeMid(cube);//中间层
ans += makeTopCross(cube);//顶层十字
ans += makeTopDir(cube);//顶层朝向
ans += makeTopCornerLoc(cube); //角块归位
bool changed;
ans += makeChangeEdge(cube, changed);//双棱对换
if (changed) {
ans += makeWhiteCross(cube); //白色十字
ans += makeWhite(cube);//白色
ans += makeMid(cube);//中间层
ans += makeTopCross(cube);//顶层十字
ans += makeTopDir(cube);//顶层朝向
ans += makeTopCornerLoc(cube); //角块归位
}
ans += makeTopEdgeLoc(cube);//棱组归位
ans += makeAll(cube);//复原
return ans;
}
bool replaceStr(std::string &str, const std::string& from, const std::string& to)
{
size_t pos = 0;
if ((pos = str.find(from, pos)) != std::string::npos) {
str.replace(pos, from.length(), to);
return true;
}
return false;
}
bool replaceAns(string &ans)
{
bool ret = false;
for (char c : {'U', 'D', 'L', 'R', 'F', 'B', 'x', 'y', 'z'})
{
string s1 = "";
s1 += c;
s1 += "' ";
s1 += c;
s1 += " ";
string s2 = " ";
ret = ret || replaceStr(ans, s1, s2);
s1 = "";
s1 += c;
s1 += " ";
s1 += c;
s1 += "' ";
ret = ret || replaceStr(ans, s1, s2);
s1 = "";
s1 += c;
s1 += " ";
s1 += c;
s1 += " ";
s1 += c;
s1 += " ";
s2 = "";
s2 += c;
s2 += "' ";
ret = ret || replaceStr(ans, s1, s2);
s1 = "";
s1 += c;
s1 += "' ";
s1 += c;
s1 += "' ";
s1 += c;
s1 += "' ";
s2 = "";
s2 += c;
s2 += " ";
ret = ret || replaceStr(ans, s1, s2);
s1 = " ";
s2 = " ";
ret = ret || replaceStr(ans, s1, s2);
}
return ret;
}
void atuoRun(vector<string>& lines)
{
vector<vector<vector<char>>>cube;
for (int i = 0; i < 6; i++) {
string s = lines[i].substr(3, lines[i].length() - 3);
vector<vector<char>>v(N, vector<char>(N));
for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)v[i][j] = s[i * N + j];
cube.push_back(v);
}
string ans = autoRunOpts(cube);
while(replaceAns(ans));
std::ofstream outFile("D:/cubeOutput.txt", std::ios::app);
if (outFile.is_open()) {
outFile << ans << "\n";
outFile.close();
}
}
// 读取文件的所有行,每一行存入一个 string
std::vector<std::string> readAllLines(const std::string& path) {
std::vector<std::string> lines;
std::ifstream in(path);
if (!in.is_open()) {
return lines; // 打开失败,返回空
}
std::string line;
while (std::getline(in, line)) {
lines.push_back(line); // 每行一个 string 对象
}
return lines;
}
// 判断文件内容是否不为空
bool fileHasContent(const std::string& path) {
std::error_code ec;
// 1. 文件必须存在
if (!fs::exists(path, ec) || ec) {
return false;
}
// 2. 文件大小必须大于 0
if (fs::file_size(path, ec) == 0 || ec) {
return false;
}
return true;
}
void run1() // 自动填写操作序列
{
const std::string filePath = "D:/cubeInput.txt";
while (true) {
if (fileHasContent(filePath)) {
// 内容不为空,读取所有行
std::vector<std::string> lines = readAllLines(filePath);
atuoRun(lines);
std::ofstream clear(filePath, std::ios::trunc);
}
// 每隔 500ms 检查一次,避免忙等占用 CPU
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
int main()
{
N = 4;
//test1(); //输入所有操作,只显示最终结果
// test2(); //每次输入1个操作,实时显示结果
run1(); // 自动填写操作序列
return 0;
}
经过漫长的调试,解BUG,第一个全自动复原终于诞生。
随机打乱序列:
F F2' D2 L' B2 R' B U2 R' B D2 D L2 D2' F2 D F U2 B' B2 B F2 R F2 R' U2' D2' R2' L U

复原序列:
x R2' F' R2 z F R2' F' R2 z z U U F R2' F' R2 x R2' F' R2 x' U F R2' F' R2 x x F R2' F' R2 F F R2' F' R2 z z U' F R2' F' R2 x' z' F' R2' F' R2 z z F R2' F' R2 x F F R2' F' R2 x' U U F R2' F' R2 z x y' F R2' F' R2 x F F R2' F' R2 x' U F R2' F' R2 z' x y' F R2' F' R2 F R2' F' R2 U F R2' F' R2 R2 R' U U R2 R' U U R2' R x' L2' L U U L2 L' x' U U R2 R' U U R2' R F U L U U L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U U L R R B U' R B B z z x' F2' F R U' R' U F2 U L U U L R R B U' R B B z z x' F2' F R U' R' U F2 F' U U F U L U' B U B U B U D B' L L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U U B L L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B L L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U U B L L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U B L L U R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U' B L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B' L U' z' x' F2' F R U' R' U F2 F' R' z' x' L' B D' F2' F R U' R' U F2 F' U' x x U' F' z z F' x U U D D F F D D F' U' R U z' U U F U' F' U' R U z' U U F U' U' F' U' R U U z' U U F U' F' U' R U U z' R U z F F U' F' U' R z' U' F U' F' U' R U z' U U F U F' U' R U' z' U U F U F' U' R U' z' U U F U F' U' R U' z' U U F U' U' F' U' R U U z' U U F U' F' U' R U U z' R U D D U' y' F R' F' y D D y' F R F' y D U D R' D R D D y' F R F' y U y' F R' F' y D D y' F R F' y D U' D' U U y' F R F' y D U U D D U U y' F R' F' y D D y' F R F' y U U y y U z U' U' L' U L U F U' F' U U R U' R' U' F' U F U z U' z U' z U' U' L' U L U F U' F' z U' z R U' R' U' F' U F U' F R U R' U' R U R' U' F' R' U' R U' R' U U R U' R' U' R U' R' U U R U R R F F R' B' R F F R' B R' z z U U R' U' R U' R' U U R z z F U F' U F U U F' R' U' R U' R' U U R z z F U F' U F U U F' U U R' U' R U' R' U U R z z F U F' U F U U F' U U D D

校验:

校验通过。
八,Bug修复
四阶魔方网页版有个小BUG,操作集支持的有遗漏。
在五阶魔方网页版中已修复。
九,五阶魔方
1,网页版程序
参考五阶魔方网页版
2,自动复原V1
因为四阶魔方自动复原里面,有些东西没考虑清楚,所以在这里,一些代码都被更通用的代码给替代了。
代码略

完整操作序列:

R4 U3 U2' B B3 F B' U4 F4 U2 B3' U3' B' D3 R' F' B' L2' R2 D3' B2 F' L R' F3 R4 B4 L2 B2 R2' U3' R4 L3 D3 B3 L3 D4' R' B4 F4' x x L2' U L2 x' F' U U L2' U L2 F z z F F U L2' U U L2 F L2' U L2 F z z x x z F L2' U L2 F L2' U L2 F F z F U L2' U' L2 F' z z x z x' F' U U L2' U L2 F z z F U L2' U U L2 F F L2' U L2 F x x U U L2' U U L2 x' F F U' L2' U L2 F L2' U L2 F L2' U L2 x F F U U L2' U U L2 F F L2' U L2 z x F U L2' U' L2 U' L2' U U L2 F' z' F' U L2' U' L2 U' L2' U U L2 F z x x F F U L2' U' L2 U' L2' U U L2 F F U L2' U' L2 U' L2' U U L2 z z F F U U L2' U' L2 U' L2' U U L2 F F U' L2' U' L2 U' L2' U U L2 z x z x' F U L2' U' L2 U' L2' U U L2 F' z z F F U L2' U' L2 U' L2' U U L2 F F x x U' L2' U' L2 U' L2' U U L2 x' F U L2' U' L2 U' L2' U U L2 F U L2' U' L2 U' L2' U U L2 F U L2' U' L2 U' L2' U U L2 F x F L2' U' L2 U' L2' U U L2 F' U U B L U' F U L U' B U B U B U D B B U' D B D B U B U' L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U U B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U U B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B' L L U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U B L L U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B L U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U B L L U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L B L L U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U' D B D B U B B L L U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L B L L U' B U B U B U D B B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B' L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L L U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U B L L U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L B L L U' B U B U B U D B B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U L U' B U B U B U D B B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B' L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 U L U' B U B U B U D B B U' L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 U L U U B L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 U L U' B U B U B U D B B U' D B D B U B B L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 U L U' B U B U B U D B B U' B L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U' x x U' F' z z F' z x U' z U F U U F' U' R z z U F U' F F U F F U z U' U' R U D U' y' F R F' y D U D R' D R D D y' F R F' y U y' F R F' y D U' D' U U y' F R F' y D U U D D U U y' F R F' y U U y y U z U' z U' U' L' U L U F U' F' U U z U' z R U' R' U' F' U F z' U R U' R' U' F' U F z U' L' U L U F U' F' z U' z U' z R U' R' U' F' U F F R U R' U' R U R' U' F' U R' U' R U' R' U U R U F U F' U F U U F' R R F F R' B' R F F R' B R' z' U' R' U' R U' R' U U R z z F U F' U F U U F' R' U' R U' R' U U R z z F U F' U F U U F' U U R' U' R U' R' U U R z z F U F' U F U U F' U U
校验:

校验通过
3,自动还原V2
V1代码考虑的还是不够,V2更严谨。
#include <iostream>
#include <string_view>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <array>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <iomanip>
#include <cmath>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
#include <thread>
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
class SingleVectorOpt
{
public:
//翻转vector、翻转二维vector的每一行
template<typename T>
static vector<T> frev(const vector<T>& v)
{
vector<T> ans;
ans.resize(v.size());
for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
return ans;
}
template<typename T>
static vector<vector<T>> frev(const vector<vector<T>>& v)
{
vector<vector<T>>ans;
for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
return ans;
}
//沿主对角线(左上角到右下角)翻转二维vector
template<typename T>
static vector<vector<T>> foverturn(const vector<vector<T>>& v)
{
vector<vector<T>> ans(v[0].size());
for (int i = 0; i < v[0].size(); i++) {
ans[i].resize(v.size());
for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
}
return ans;
}
//顺时针旋转二维vector
template<typename T>
static vector<vector<T>> frotation(const vector<vector<T>>& v)
{
return frev(foverturn(v));
}
//从vector(一维或2维)中删除所有的x
template<typename T>
static void deletAllX(vector<T>& v, T x)
{
for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
}
template<typename T>
static void deletAllX(vector<vector<T>>& v, T x)
{
for (auto& vi : v)deletAllX(vi, x);
}
// 去掉相邻重复元素
template<typename T>
static void deleteNeiborSame(vector<T>& v)
{
v.erase(std::unique(v.begin(), v.end()), v.end());
}
//判断数组去掉相邻重复数之后有多少个不同的数
template<typename T>
static int getDifNum(const vector<T>& v)
{
auto v2 = v;
deleteNeiborSame(v2);
return v2.size();
}
//vector乘一个数
template<typename T1, typename T2>
static void fcheng(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
}
//vector加一个数
template<typename T1, typename T2>
static void fjia(vector<T1>& v, T2 n)
{
for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
}
//二维数组每一行排序
template<typename T>
static void sortEveryLine(vector<vector<T>>& v)
{
for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
}
//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
template<typename T, class P>
static inline vector<int>firstInLeft(vector<T>v, P pr)
{
vector<int> ans;
if (v.size() == 0)return ans;
stack<T>st;
st.push(0);
ans.push_back(-1);
for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
{
while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
if (st.empty())ans.push_back(-1);
else ans.push_back(st.top());
st.push(i);
}
return ans;
}
//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fminlef(vector<T> v)
{
return firstInLeft(v, [](T a, T b) {return a < b; }); //可换为自定义函数
}
//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fminlef2(vector<T> v)
{
return firstInLeft(v, [](T a, T b) {return a <= b; }); //可换为自定义函数
}
//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fmaxlef(vector<T> v)
{
fcheng(v, -1);
vector<int>ans = fminlef(v);
return ans;
}
//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
template<typename T>
static vector<int> fmaxlef2(vector<T> v)
{
fcheng(v, -1);
vector<int>ans = fminlef2(v);
return ans;
}
//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fminrig(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fminlef(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fminrig2(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fminlef2(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fmaxrig(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fmaxlef(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
template<typename T>
static vector<int> fmaxrig2(vector<T> v)
{
vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
fcheng(v2, -1);
fjia(v2, v.size() - 1);
return frev(v2);
}
// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
static map<int, map<int, int>> splitAtHalf(vector<int>& v)
{
vector<int>s;
int n = 0;
s.push_back(n);
for (auto x : v) {
n += x;
s.push_back(n);
}
map<int, map<int, int>>ans;
for (int i = 0; i < v.size(); i++) {
int id = i;
for (int j = i; j < v.size(); j++) {
while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
ans[i][j] = id;
}
}
return ans;
}
//获取所有的众数
template<typename T>
static vector<T> getMost(const vector<T>& v)
{
int n = 0;
map<T, int>m;
for (auto x : v)n = max(n, ++m[x]);
vector<T>ans;
for (auto p : m)if (p.second == n)ans.push_back(p.first);
return ans;
}
};
#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行
int N;
vector<vector<vector<char>>> Init()
{
vector<vector<vector<char>>> ans;
for (auto c : { 'W','Y','G','B','R','O' }) //上下左右前后
{
vector<char> temp(N, c);
vector<vector<char>>v(N, temp);
ans.push_back(v);
}
return ans;
}
void show(vector<vector<vector<char>>>& cube)
{
cout << endl << "U: ";
for (auto v : cube[0])for (auto ch : v)cout << ch;
cout << endl << "D: ";
for (auto v : cube[1])for (auto ch : v)cout << ch;
cout << endl << "L: ";
for (auto v : cube[2])for (auto ch : v)cout << ch;
cout << endl << "R: ";
for (auto v : cube[3])for (auto ch : v)cout << ch;
cout << endl << "F: ";
for (auto v : cube[4])for (auto ch : v)cout << ch;
cout << endl << "B: ";
for (auto v : cube[5])for (auto ch : v)cout << ch;
cout << endl;
}
void rotate(vector<vector<vector<char>>>& cube, string s);
void rotate2(vector<vector<vector<char>>>& cube, string s)
{
if (s.length() == 1)s += "1";
if (s[0] == 'U')
{
cube[0] = Frotation(cube[0]);
for (int i = 0; i < s[1] - '0'; i++) {
auto v = cube[2][i];
cube[2][i] = cube[4][i], cube[4][i] = cube[3][i], cube[3][i] = cube[5][i], cube[5][i] = v;
}
return;
}
string s2 = "U";
if (s[0] == 'D') {
rotate(cube, "x");
rotate(cube, "x");
rotate(cube, s2 + s[1]);
rotate(cube, "x");
rotate(cube, "x");
return;
}
if (s[0] == 'R')
{
rotate(cube, "y'");
rotate(cube, s2 + s[1]);
rotate(cube, "y");
return;
}
if (s[0] == 'L')
{
rotate(cube, "y");
rotate(cube, s2 + s[1]);
rotate(cube, "y'");
return;
}
if (s[0] == 'F')
{
rotate(cube, "x");
rotate(cube, s2 + s[1]);
rotate(cube, "x'");
return;
}
if (s[0] == 'B')
{
rotate(cube, "x'");
rotate(cube, s2 + s[1]);
rotate(cube, "x");
return;
}
}
void rotate(vector<vector<vector<char>>>& cube, string s)
{
int len = s.length();
if (s[len - 1] == '\'') {
string s2 = s.substr(0, len - 1);
rotate(cube, s2);
rotate(cube, s2);
rotate(cube, s2);
return;
}
if (s == "x")
{
cube[3] = Frotation(cube[3]);
cube[2] = Frotation(Frotation(Frotation(cube[2])));
auto v = cube[0];
cube[0] = cube[4];
cube[4] = Frev<vector<char>>(cube[1]); //上下翻转
cube[1] = Frev<char>(cube[5]); //翻转每一行
cube[5] = Frev<char>(Frev<vector<char>>(v));
return;
}
if (s == "z") {
cube[0] = Frotation(cube[0]);
cube[1] = Frotation(cube[1]);
auto v = cube[2];
cube[2] = cube[4], cube[4] = cube[3], cube[3] = cube[5], cube[5] = v;
return;
}
if (s == "y") {
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "z");
rotate(cube, "x");
rotate(cube, "z");
return;
}
rotate2(cube, s);
}
void test1() //输入所有操作,只显示最终结果
{
vector<string>opts;
string c;
while (cin >> c)opts.push_back(c);
auto cube = Init();
for (auto c : opts) {
rotate(cube, c);
}
show(cube);
}
void test2() //每次输入1个操作,实时显示结果
{
auto cube = Init();
string c;
while (cin >> c) {
rotate(cube, c);
show(cube);
cout << endl;
}
}
string makeOpt(const string& opt, int num)
{
if (num == 1)return opt;
string s1 = opt;
string s2 = std::to_string(num);
if (s1.length() == 1)return s1 + s2; //不带'
//带'
string s3, s4;
s3 += s1[0], s4 += s1[1];
return s3 + s2 + s4;
}
#define AnsAdd(s) ans += s;ans += " "; rotate(cube, s);
// F1-F9 是三阶魔方的公式
#define F1 AnsAdd("y'");AnsAdd("F");AnsAdd("R'");AnsAdd("F'");AnsAdd("y");AnsAdd("D");AnsAdd("D");AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块1 y' F R' F' y D D y' F R F' y
#define F2 AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块2 y' F R F' y
#define F3 AnsAdd("R'");AnsAdd("D");AnsAdd("R");// 白色角块3 R' D' R
#define F4 AnsAdd("U'");AnsAdd("L'");AnsAdd("U");AnsAdd("L");AnsAdd("U");AnsAdd("F");AnsAdd("U'");AnsAdd("F'");// 中层棱块1 U' L' U L U F U' F'
#define F5 AnsAdd("U");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");AnsAdd("U");AnsAdd("F");// 中层棱块2 U R U' R' U' F' U F
#define F6 AnsAdd("F");AnsAdd("R");AnsAdd("U");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");// 顶层十字 F R U R' U' F'
#define F7 AnsAdd("R'");AnsAdd("U'");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U");AnsAdd("U");AnsAdd("R"); // 小鱼1 R' U' R U' R' U U R
#define F8 AnsAdd("F");AnsAdd("U");AnsAdd("F'");AnsAdd("U");AnsAdd("F");AnsAdd("U");AnsAdd("U");AnsAdd("F'"); // 小鱼2 F U F' U F U U F'
#define F9 AnsAdd("R");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B'");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B");AnsAdd("R'"); // 换角 R R F F R' B' R F F R' B R'
//F10 单棱对换 R2 U U R2 U U R2' x' L2' U U L2 x' U U R2 U U R2'
#define F10_1(id) AnsAdd(makeOpt("R",id+1));AnsAdd(makeOpt("R'",id)); //R2
#define F10_2(id) AnsAdd(makeOpt("R'",id+1));AnsAdd(makeOpt("R",id)); //R2'
#define F10_3 AnsAdd("U");AnsAdd("U"); //U U
#define F10_4(id) F10_3;F10_1(id);F10_3;F10_2(id); //U U R2 U U R2'
#define F10(id) F10_1(id);F10_4(id);AnsAdd("x'");AnsAdd(makeOpt("L'",id+1));AnsAdd(makeOpt("L",id));F10_3;\
AnsAdd(makeOpt("L",id+1));AnsAdd(makeOpt("L'",id));AnsAdd("x'");F10_4(id);
//F11 U位棱组翻转
#define F11 AnsAdd("U");AnsAdd("U");AnsAdd("B");AnsAdd("L");AnsAdd("U'");
//F12 棱块合并
#define F12(id) AnsAdd(makeOpt("F'",id)); AnsAdd("F"); AnsAdd("R"); AnsAdd("U'"); AnsAdd("R'"); AnsAdd("U"); AnsAdd(makeOpt("F",id));AnsAdd("F'");
//F13 双棱对换
#define F13_1 F10_3;AnsAdd("F");AnsAdd("F");
#define F13_2 AnsAdd("R2");F10_3;AnsAdd("R2'");
#define F13_3 F13_2;F13_1;F13_1;F13_1;F13_2;
#define F13 F13_3;AnsAdd("x'");F13_3;AnsAdd("x'");F13_3;
// U位R位棱组交叉
#define F14(id) F11;AnsAdd("z'");AnsAdd("x'");F12(id);AnsAdd("R'");AnsAdd("z'");AnsAdd("x'");AnsAdd("L'");AnsAdd("B");AnsAdd("D'");F12(id);
#define F15 AnsAdd("z'");AnsAdd("x'");F12(high);AnsAdd("x'");AnsAdd("F");AnsAdd("R'");AnsAdd("F'");AnsAdd("D");F12(high);AnsAdd("U'");\
AnsAdd("x'");AnsAdd("U'");AnsAdd("B'");AnsAdd("D'");F12(high);
#define F16 AnsAdd("z'");AnsAdd("x'");F12(high);AnsAdd("F'");AnsAdd("U");AnsAdd("R");AnsAdd("R");AnsAdd("L");AnsAdd("D");AnsAdd("D");AnsAdd("F");F12(high);
string makeDir(vector<vector<vector<char>>>& cube) //调整白色面朝上
{
string ans;
int id = N / 2;
if (cube[1][id][id] == 'W') {
AnsAdd("x");
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][id][id] == 'W')break;
}
if (cube[0][id][id] != 'W') {
AnsAdd("x");
}
return ans;
}
string makeCenterEdge(vector<vector<vector<char>>>& cube, int id)
{
string ans; //待更新 对于N>5涉及
return ans;
}
string makeCenterWithFunc(vector<vector<vector<char>>>& cube, int id, string(*func)(vector<vector<vector<char>>>&, int, char))
{
string ans = makeDir(cube);
AnsAdd("x");
//前黄 后白
ans += func(cube, id, 'W');
AnsAdd("x'");
//上白
for (int i = 0; i < 4; i++) {
ans += func(cube, id, 'W');
AnsAdd("z");
}
AnsAdd("x");
AnsAdd("x");
//上黄
for (int i = 0; i < 4; i++) {
ans += func(cube, id, 'Y');
AnsAdd("z");
}
for (int i = 0; i < 4; i++) {
if (cube[4][N / 2][N / 2] == 'R')break;
AnsAdd("z");
}
//上黄 前红
AnsAdd("x");
AnsAdd("z");
//上红 前绿
ans += func(cube, id, 'B');
AnsAdd("x'");
ans += func(cube, id, 'B');
AnsAdd("z");
AnsAdd("z");
ans += func(cube, id, 'B');
//至此,左黄 上蓝 右白 都完成了
AnsAdd("x");
AnsAdd("x");
ans += func(cube, id, 'O');
AnsAdd("x'");
ans += func(cube, id, 'O');
AnsAdd("x");
ans += func(cube, id, 'G');
return ans;
}
string makeCenterEdgeLocFtoU(vector<vector<vector<char>>>& cube, int id, char c)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("F");
if (cube[4][N / 2][id] != c)continue;
for (int i = 0; i < 4; i++) {
if (cube[0][N / 2][id] == c)break;
AnsAdd("U");
}
AnsAdd(makeOpt("L'", id + 1));
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][N / 2][id] != c)break;
}
AnsAdd(makeOpt("L", id + 1));
}
return ans;
}
string makeCenterEdgeLoc(vector<vector<vector<char>>>& cube, int id)
{
return makeCenterWithFunc(cube, id, makeCenterEdgeLocFtoU);
}
string makeCenterCornerLocFtoU(vector<vector<vector<char>>>& cube, int id, char c)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("F");
if (cube[4][id][id] != c)continue;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][N - 1 - id][id] != c)break;
}
AnsAdd(makeOpt("L'", id + 1));
AnsAdd("U'");
AnsAdd(makeOpt("L", id + 1));
AnsAdd("U'");
AnsAdd(makeOpt("L'", id + 1));
AnsAdd("U");
AnsAdd("U");
AnsAdd(makeOpt("L", id + 1));
}
return ans;
}
string makeCenterCornerLoc(vector<vector<vector<char>>>& cube, int id)
{
return makeCenterWithFunc(cube, id, makeCenterCornerLocFtoU);
}
string makeCenterId(vector<vector<vector<char>>>& cube, int id)
{
string ans = makeCenterEdge(cube, id);
ans += makeCenterEdgeLoc(cube, id);
ans += makeCenterCornerLoc(cube, id);
return ans;
}
string makeAllCenterCenter(vector<vector<vector<char>>>& cube)
{
if (N % 2)return "";
return makeCenterWithFunc(cube, N / 2 - 1, makeCenterCornerLocFtoU);
}
string makeAllCenter(vector<vector<vector<char>>>& cube)
{
string ans = makeAllCenterCenter(cube);
for (int i = (N - 3) / 2; i > 0; i--) { //中心大正方形逐步扩圈
ans += makeCenterId(cube, i);
}
return ans;
}
int getId(char a, char b)
{
vector<string> v{ "RW", "BW", "OW", "GW", "OY", "BY", "RY", "GY", "OG", "OB", "RB", "RG" };
for (int i = 0; i < 12; i++) {
if (v[i][0] == a && v[i][1] == b)return i;
}
return getId(b, a) + 12;
}
template<typename T>
int getInvertNum(vector<T>v)
{
int n = 0;
for (int i = 0; i < v.size(); i++) {
for (int j = i + 1; j < v.size(); j++) {
if (v[i] > v[j])n++;
}
}
return n;
}
#define ForEachEdgeUp(func) func;rotate(cube, "U");func;rotate(cube, "U");func;rotate(cube, "U");func;
#define ForEachEdgeLR(func) rotate(cube, "F");func;rotate(cube, "F");rotate(cube, "F");func;
// 依次把12个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdge(func) ForEachEdgeUp(func);rotate(cube, "x");rotate(cube, "x");ForEachEdgeUp(func);\
ForEachEdgeLR(func);rotate(cube, "z");rotate(cube, "z");ForEachEdgeLR(func);
#define GetTwoEdgeId v.push_back(getId(cube[4][0][id], cube[0][N - 1][id]));v.push_back(getId(cube[0][N - 1][N - 1 - id], cube[4][0][N - 1 - id]));
bool checkEdgeLocStatus(vector<vector<vector<char>>> cube, int id) //check***系列函数中,少有的非const&的cube参数,这里不要用&
{
vector<int>v;
ForEachEdge(GetTwoEdgeId);
return getInvertNum(v) % 2 == 0;
}
string makeEdgeLocStatus(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 1; i < N / 2; i++) {
if (!checkEdgeLocStatus(cube, i)) {
F10(i);//交换2个棱块
}
}
return ans;
}
#define ForEachEdgeUp2(func) func;AnsAdd("U");func;AnsAdd("U");func;AnsAdd("U");func;
#define ForEachEdgeLR2(func) AnsAdd("F");func;AnsAdd("F");AnsAdd("F");func;
// 依次把12个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdge2(func) ForEachEdgeUp2(func);AnsAdd( "x");AnsAdd( "x");ForEachEdgeUp2(func);\
ForEachEdgeLR2(func);AnsAdd( "z");AnsAdd( "z");ForEachEdgeLR2(func);
// 依次把10个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdgeExceptLR(func) ForEachEdgeUp2(func);AnsAdd( "B");AnsAdd( "U");AnsAdd( "B");AnsAdd( "U");AnsAdd( "B");AnsAdd( "U");\
AnsAdd( "D");AnsAdd( "B");AnsAdd( "B"); ForEachEdgeUp2(func);AnsAdd( "D");AnsAdd( "B");AnsAdd( "D");AnsAdd( "B");AnsAdd( "U");\
AnsAdd( "B");AnsAdd( "U");func;AnsAdd( "U");func;
#define case1 (cube[0][N - 1][mid] == target[0] && cube[4][0][mid] == target[1])
#define case2 (cube[0][N - 1][mid] == target[1] && cube[4][0][mid] == target[0])
#define case3 (cube[0][N - 1][high] == target[0] && cube[4][0][high] == target[1])
#define case4 (cube[0][N - 1][high] == target[1] && cube[4][0][high] == target[0])
#define FindEdgeWithTarget if (case1||case2||((N%2==0 && high==mid+1)&&(case3||case4)))goto here1;
#define FindEdgeWithDif(h) if (cube[0][N - 1][mid] != cube[0][N - 1][high] || cube[4][0][mid] !=cube[4][0][high] || \
cube[0][N - 1][mid] != cube[0][N - 1][low] || cube[4][0][mid] != cube[4][0][low])goto h;
int checkFinishEdgeNum(vector<vector<vector<char>>> cube, int low, int mid, int high)//check***系列函数中,少有的非const&的cube参数,这里不要用&
{
int num = 0;
ForEachEdge(if (cube[4][0][high] == cube[4][0][mid] && cube[0][N - 1][high] == cube[0][N - 1][mid] &&
cube[4][0][low] == cube[4][0][mid] && cube[0][N - 1][low] == cube[0][N - 1][mid])num++;);
return num;
}
string makeEdge1(vector<vector<vector<char>>>& cube, int low, int mid, int high)
{
string ans;
//checkFinishEdgeNum<10, 正面U位棱组mid和high不属于同一棱组
string target;
target += cube[0][N - 1][high];
target += cube[4][0][high];
char c1 = cube[0][N - 1][mid], c2 = cube[4][0][mid];
AnsAdd("F");//high处是target的棱组停留在正面R位
FindEdgeWithTarget;
AnsAdd("U");
AnsAdd("L");//一个mid/high处不是target的棱组停留在正面L位
ForEachEdgeExceptLR(FindEdgeWithTarget);
here1:
//mid/high处是target的棱组停留在正面U位
if (cube[0][N - 1][mid] == target[1] && cube[4][0][mid] == target[0]) {
F11;
}
if (N % 2 == 0 && high == mid + 1 && cube[0][N - 1][high] == target[1] && cube[4][0][high] == target[0]) {
F11;
}
//此时,正面U位棱组mid处和正面R位棱组high处属于同一棱组,且方向一致
AnsAdd("U");
AnsAdd("L");//mid处是target的棱组停留在正面L位
ForEachEdgeExceptLR(FindEdgeWithDif(here2));
here2:
//带dif的棱组停留在正面U位
if (cube[0][N - 1][mid] == cube[0][N - 1][low] && cube[4][0][mid] == cube[4][0][low]) {
F11;
AnsAdd("L'");
}
//正面U位棱组mid处和high处不属于同一棱组
AnsAdd("R");
AnsAdd("R");
AnsAdd("B");
AnsAdd("U'");
AnsAdd("R");
AnsAdd("B");
AnsAdd("B");
AnsAdd("z");
AnsAdd("z");
AnsAdd("x'");
F12(high);
return ans;
}
string makeEdge2(vector<vector<vector<char>>>& cube, int low, int mid, int high)
{
string ans;
//checkFinishEdgeNum<10, 所有棱组的low、mid和high都属于同一棱组,但是有2k(k>=2)个棱组都存在2个棱块互换,且其中一个就在正面U位
AnsAdd("F"); //R位
ForEachEdgeExceptLR(if (cube[0][N - 1][mid] != cube[0][N - 1][high])goto here3;);//U位
here3:
AnsAdd("U");
AnsAdd("L");//L位
here4:
ForEachEdgeExceptLR(if (cube[0][N - 1][mid] != cube[0][N - 1][high])goto here4;);//U位
AnsAdd("z'");
AnsAdd("x'");
F12(high);
return ans;
}
#define InSame(a, b, c, d) (a == c || a == d) && (b == c || b == d)
string makeAllEdgeLast(vector<vector<vector<char>>>& cube, int low, int mid, int high)
{
string ans;
//2个棱组有问题
ForEachEdge2(FindEdgeWithDif(here6));
here6:
//U位棱组有问题
AnsAdd("F"); //R位
FindEdgeWithDif(here7);
AnsAdd("U");
AnsAdd("L");
ForEachEdgeExceptLR(FindEdgeWithDif(here7));
here7:
//U位和R位棱组有问题
if (high == low + 1) {
// U位R位棱组交叉
F14(high);
return ans;
}
bool flag1 = InSame(cube[0][N - 1][low], cube[4][0][low], cube[0][N - 1][mid], cube[4][0][mid]);
bool flag2 = InSame(cube[0][N - 1][high], cube[4][0][high], cube[0][N - 1][mid], cube[4][0][mid]);
if (flag1 && flag2) {
// case1
F15;
return ans;
}
if (flag1 || flag2) {
//case3
bool flag3 = cube[0][N - 1][low] == cube[0][N - 1][mid] && cube[4][0][low] == cube[4][0][mid];
bool flag4 = cube[0][N - 1][high] == cube[0][N - 1][mid] && cube[4][0][high] == cube[4][0][mid];
if (flag3 || flag4) {
AnsAdd("R");
AnsAdd("F");
AnsAdd("U");
}
AnsAdd("R");
AnsAdd("F");
AnsAdd("U");
flag4 = cube[0][N - 1][high] == cube[0][N - 1][mid] && cube[4][0][high] == cube[4][0][mid];
if (flag4) {
F11;
}
AnsAdd("y'");
flag1 = InSame(cube[0][N - 1][low], cube[4][0][low], cube[0][N - 1][mid], cube[4][0][mid]);
if (flag1) {
F11;
AnsAdd("L'");
}
AnsAdd("z'");
F12(high);
return ans;
}
//case2
char c1 = cube[0][N - 1][low];
AnsAdd("F'");
char c2 = cube[0][N - 1][mid];
AnsAdd("F");
if (c1 != c2) {
F11;
}
F16;
return ans;
}
string makeAllEdgeOnce(vector<vector<vector<char>>>& cube, int low, int mid, int high)
{
if (checkFinishEdgeNum(cube, low, mid, high) == 10)return makeAllEdgeLast(cube, low, mid, high);
string ans;
bool flag = false;
ForEachEdge2(if (cube[4][0][high] != cube[4][0][mid] && cube[4][0][high] != cube[0][N - 1][mid]) { flag = true; goto here5; }
if (cube[0][N - 1][high] != cube[4][0][mid] && cube[0][N - 1][high] != cube[0][N - 1][mid]) { flag = true; goto here5; }
if (cube[4][0][low] != cube[4][0][mid] && cube[4][0][low] != cube[0][N - 1][mid]) { flag = true; goto here5; }
if (cube[0][N - 1][low] != cube[4][0][mid] && cube[0][N - 1][low] != cube[0][N - 1][mid]) { flag = true; goto here5; })
here5:
if (flag) {
if (cube[4][0][low] != cube[4][0][mid] && cube[4][0][low] != cube[0][N - 1][mid]) {
F11;
}
else if (cube[0][N - 1][low] != cube[4][0][mid] && cube[0][N - 1][low] != cube[0][N - 1][mid]) {
F11;
}
//此时,正面U位棱组一定满足,mid和high不属于同一棱组
ans += makeEdge1(cube, low, mid, high);
}
else {
//此时,所有棱组的low、mid和high都属于同一棱组,但是有2k(k>=2)个棱组都存在2个棱块互换,且其中一个就在正面U位
ans += makeEdge2(cube, low, mid, high);
}
return ans;
}
//难点在于精确定义用什么量作为无穷递降法的依据,所有情况都要考虑到,否则就会出现低概率无限循环
//我这套方案是基于二元组,第一顺位是提高checkFinishEdgeNum,checkFinishEdgeNum不变的情况下是提高mid=high的配对数
string makeAllEdge(vector<vector<vector<char>>>& cube)
{
string ans;
int mid = (N - 1) / 2;
for (int i = N / 2 - 1; i > 0; i--) { //棱块从内往外扩
int id = N - 1 - i; // i <= mid < id, mid是基准,i和id是一对
while (true) {
auto num = checkFinishEdgeNum(cube, i, mid, id);
if (num == 12)break;
ans += makeAllEdgeOnce(cube, i, mid, id); //一般每次调用makeAllEdgeOnce二元组都会进步,保证每次都不能退步,且不会连续2次原地踏步
}
}
return ans;
}
string makeUUUU(vector<vector<vector<char>>>& cube) //白色层方向回正
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][N - 1][1] == 'W' && cube[4][0][1] == 'R') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][1][N - 1] == 'W' && cube[3][0][1] == 'B') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][1][0] == 'W' && cube[2][0][1] == 'G') {
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[0][0][1] == 'W' && cube[5][0][1] == 'O') {
return ans;
}
}
return ans;
}
bool checkWhiteCross(const vector<vector<vector<char>>>& cube)// 检查白色十字是否完成
{
char whiteColor = 'W';
if (cube[0][0][1] != whiteColor || cube[0][N - 1][1] != whiteColor || cube[0][1][0] != whiteColor || cube[0][1][N - 1] != whiteColor) {
return false;
}
if (cube[2][0][1] != 'G' || cube[3][0][1] != 'B' || cube[4][0][1] != 'R') {
return false;
}
return true;
}
string makeWhiteCrossOnce(vector<vector<vector<char>>>& cube)
{
string ans = "";
for (int i = 0; i < 4; i++) {
AnsAdd("D");
if (cube[4][N - 1][1] == 'W') {
ans += makeUUUU(cube);
char c = cube[1][N - 1][1];
if (c == 'B') {
AnsAdd("U");
}
if (c == 'O') {
AnsAdd("U");
AnsAdd("U");
}
if (c == 'G') {
AnsAdd("U'");
}
AnsAdd("F'");
AnsAdd("U'");
AnsAdd("R");
return ans;
}
if (cube[1][N - 1][1] == 'W') {
ans += makeUUUU(cube);
char c = cube[4][N - 1][1];
if (c == 'B') {
AnsAdd("U");
}
if (c == 'O') {
AnsAdd("U");
AnsAdd("U");
}
if (c == 'G') {
AnsAdd("U'");
}
AnsAdd("F");
AnsAdd("F");
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][1][N - 1] == 'W' || cube[3][1][0] == 'W') {
while (cube[0][N - 1][1] == 'W') {
AnsAdd("U");
}
AnsAdd("F");
return ans;
}
}
ans += makeUUUU(cube);
string s = "BOGR";
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[0][N - 1][1] != 'W' || cube[4][0][1] != s[i]) {
AnsAdd("F");
AnsAdd("F");
return ans;
}
}
return ans;
}
string makeWhiteCross(vector<vector<vector<char>>>& cube)
{
string ans;
while (true) {
ans += makeDir(cube);
ans += makeUUUU(cube);
if (checkWhiteCross(cube))break;
ans += makeWhiteCrossOnce(cube);
}
return ans;
}
bool checkWhite(const vector<vector<vector<char>>>& cube)// 检查白色是否完成
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][1] || cube[i][0][N - 1] != cube[i][0][1])return false;
}
return true;
}
string makeWhiteOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("D");
ans += makeUUUU(cube);
string t;
t += cube[1][N - 1][N - 1];
t += cube[3][N - 1][0];
t += cube[4][N - 1][N - 1];
sort(t.begin(), t.end());
if (t == "BOW") {
AnsAdd("U");
}
if (t == "GOW") {
AnsAdd("U");
AnsAdd("U");
}
if (t == "GRW") {
AnsAdd("U");
AnsAdd("U");
AnsAdd("U");
}
if (cube[1][N - 1][N - 1] == 'W') {
F1;
return ans;
}
if (cube[4][N - 1][N - 1] == 'W') {
F2;
return ans;
}
if (cube[3][N - 1][0] == 'W') {
F3;
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[4][0][N - 1] != cube[4][0][1] || cube[3][0][0] != cube[3][0][1]) {
F2;
return ans;
}
}
return ans;
}
string makeWhite(vector<vector<vector<char>>>& cube)
{
string ans;
while (true) {
ans += makeDir(cube);
if (checkWhite(cube))break;
ans += makeWhiteOnce(cube);
}
return ans;
}
bool checkMid(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][1][0] != cube[i][1][1] || cube[i][1][N - 1] != cube[i][1][1])return false;
}
return true;
}
string makeMidOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
string t;
t += cube[0][N - 1][1];
t += cube[4][0][1];
if (t[0] != 'Y' && t[1] != 'Y') {
while (cube[4][0][1] != cube[4][1][1]) {
AnsAdd("z");
AnsAdd("U'");
}
if (t == "BR" || t == "RG" || t == "GO" || t == "OB") {
F4;
}
else {
F5;
}
return ans;
}
}
for (int i = 0; i < 4; i++) {
AnsAdd("z");
if (cube[4][1][0] != cube[4][1][1]) {
F4;
}
else if (cube[4][1][N - 1] != cube[4][1][1]) {
F5;
}
}
return ans;
}
string makeMid(vector<vector<vector<char>>>& cube)
{
string ans = makeDir(cube) + " ";
ans += makeUUUU(cube);
AnsAdd("y");
AnsAdd("y");
//从此,白色在下面,不能再调用makeDir和makeUUUU!!!!
while (true) {
if (checkMid(cube))break;
ans += makeMidOnce(cube);
}
return ans;
}
bool checkTopCross(const vector<vector<vector<char>>>& cube)
{
int num = 0;
if (cube[0][0][1] == 'Y')num++;
if (cube[0][N - 1][1] == 'Y')num++;
if (cube[0][1][0] == 'Y')num++;
if (cube[0][1][N - 1] == 'Y')num++;
return num == 4;
}
string makeTopCrossOnce(vector<vector<vector<char>>>& cube)
{
string ans;
int num = 0;
if (cube[0][0][1] == 'Y')num++;
if (cube[0][N - 1][1] == 'Y')num++;
if (cube[0][1][0] == 'Y')num++;
if (cube[0][1][N - 1] == 'Y')num++;
if (num == 2) {
while (cube[0][1][0] != 'Y') {
AnsAdd("U");
}
if (cube[0][N - 1][1] == 'Y') {
AnsAdd("U");
}
}
F6;
return ans;
}
string makeTopCross(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCross(cube)) {
ans += makeTopCrossOnce(cube);
}
return ans;
}
bool checkTopDir(const vector<vector<vector<char>>>& cube)
{
int num = 0;
if (cube[0][0][0] == 'Y') num++;
if (cube[0][0][N - 1] == 'Y') num++;
if (cube[0][N - 1][0] == 'Y') num++;
if (cube[0][N - 1][N - 1] == 'Y') num++;
return num == 4;
}
string makeTopDirOnce(vector<vector<vector<char>>>& cube)
{
string ans;
int num = 0;
if (cube[0][0][0] == 'Y') num++;
if (cube[0][0][N - 1] == 'Y') num++;
if (cube[0][N - 1][0] == 'Y') num++;
if (cube[0][N - 1][N - 1] == 'Y') num++;
if (num == 0) {
while (cube[2][0][0] != 'Y') {
AnsAdd("U");
}
F7;
return ans;
}
if (num == 2) {
while (cube[5][0][N - 1] != 'Y') {
AnsAdd("U");
}
F7;
return ans;
}
while (cube[0][0][0] != 'Y') {
AnsAdd("U");
}
if (cube[4][0][0] == 'Y') {
F7;
return ans;
}
F8;
return ans;
}
string makeTopDir(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopDir(cube)) {
ans += makeTopDirOnce(cube);
}
return ans;
}
bool checkTopCornerLoc(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][N - 1])return false;
}
return true;
}
string makeTopCornerLocOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[3][0][0] == cube[3][0][N - 1])break;
}
F9;
return ans;
}
string makeTopCornerLoc(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopCornerLoc(cube)) {
ans += makeTopCornerLocOnce(cube);
}
return ans;
}
string makeChangeEdge(vector<vector<vector<char>>>& cube, bool& changed)
{
string ans;
changed = false;
//方向回正
while (cube[4][1][1] != 'O') {
AnsAdd("z");
}
while (cube[4][0][0] != cube[4][1][0]) {
AnsAdd("U");
}
vector<char>v;
for (int i = 2; i <= 5; i++) {
v.push_back(cube[i][0][1]);
}
// 复原是GBOR
if (getInvertNum(v) % 2 == 0) {
F13;
changed = true;
}
return ans;
}
bool checkTopEdgeLoc(const vector<vector<vector<char>>>& cube)
{
for (int i = 2; i <= 5; i++) {
if (cube[i][0][0] != cube[i][0][1])return false;
}
return true;
}
string makeTopEdgeLocOnce(vector<vector<vector<char>>>& cube)
{
string ans;
for (int i = 0; i < 4; i++) {
AnsAdd("U");
if (cube[4][0][0] == cube[4][0][1])break;
}
F7;
AnsAdd("z");
AnsAdd("z");
F8;
return ans;
}
string makeTopEdgeLoc(vector<vector<vector<char>>>& cube)
{
string ans;
while (!checkTopEdgeLoc(cube)) {
ans += makeTopEdgeLocOnce(cube);
}
return ans;
}
string makeAll(vector<vector<vector<char>>>& cube)
{
string ans;
while (cube[4][0][0] != cube[4][1][0]) {
AnsAdd("U");
}
while (cube[4][N - 1][0] != cube[4][1][0]) {
AnsAdd("D");
}
return ans;
}
string autoRunOpts(vector<vector<vector<char>>>& cube)
{
string ans = makeAllCenter(cube); //中心大正方形合并
ans += makeEdgeLocStatus(cube); //棱块位置奇偶性
ans += makeAllEdge(cube); //棱块合并
ans += makeWhiteCross(cube); //白色十字
ans += makeWhite(cube);//白色
ans += makeMid(cube);//中间层
ans += makeTopCross(cube);//顶层十字
ans += makeTopDir(cube);//顶层朝向
ans += makeTopCornerLoc(cube); //角块归位
bool changed;
ans += makeChangeEdge(cube, changed);//双棱对换
if (changed) {
ans += makeWhiteCross(cube); //白色十字
ans += makeWhite(cube);//白色
ans += makeMid(cube);//中间层
ans += makeTopCross(cube);//顶层十字
ans += makeTopDir(cube);//顶层朝向
ans += makeTopCornerLoc(cube); //角块归位
}
ans += makeTopEdgeLoc(cube);//棱组归位
ans += makeAll(cube);//复原
return ans;
}
bool replaceStr(std::string& str, const std::string& from, const std::string& to)
{
size_t pos = 0;
if ((pos = str.find(from, pos)) != std::string::npos) {
str.replace(pos, from.length(), to);
return true;
}
return false;
}
bool replaceAns(string& ans)
{
bool ret = false;
for (char c : {'U', 'D', 'L', 'R', 'F', 'B', 'x', 'y', 'z'})
{
string s1 = "";
s1 += c;
s1 += "' ";
s1 += c;
s1 += " ";
string s2 = " ";
ret = ret || replaceStr(ans, s1, s2);
s1 = "";
s1 += c;
s1 += " ";
s1 += c;
s1 += "' ";
ret = ret || replaceStr(ans, s1, s2);
s1 = "";
s1 += c;
s1 += " ";
s1 += c;
s1 += " ";
s1 += c;
s1 += " ";
s2 = "";
s2 += c;
s2 += "' ";
ret = ret || replaceStr(ans, s1, s2);
s1 = "";
s1 += c;
s1 += "' ";
s1 += c;
s1 += "' ";
s1 += c;
s1 += "' ";
s2 = "";
s2 += c;
s2 += " ";
ret = ret || replaceStr(ans, s1, s2);
s1 = " ";
s2 = " ";
ret = ret || replaceStr(ans, s1, s2);
}
return ret;
}
void atuoRun(vector<string>& lines)
{
vector<vector<vector<char>>>cube;
for (int i = 0; i < 6; i++) {
string s = lines[i].substr(3, lines[i].length() - 3);
vector<vector<char>>v(N, vector<char>(N));
for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)v[i][j] = s[i * N + j];
cube.push_back(v);
}
string ans = autoRunOpts(cube);
while (replaceAns(ans));
std::ofstream outFile("D:/cubeOutput.txt", std::ios::app);
if (outFile.is_open()) {
outFile << ans << "\n";
outFile.close();
}
}
// 读取文件的所有行,每一行存入一个 string
std::vector<std::string> readAllLines(const std::string& path) {
std::vector<std::string> lines;
std::ifstream in(path);
if (!in.is_open()) {
return lines; // 打开失败,返回空
}
std::string line;
while (std::getline(in, line)) {
lines.push_back(line); // 每行一个 string 对象
}
return lines;
}
// 判断文件内容是否不为空
bool fileHasContent(const std::string& path) {
std::error_code ec;
// 1. 文件必须存在
if (!fs::exists(path, ec) || ec) {
return false;
}
// 2. 文件大小必须大于 0
if (fs::file_size(path, ec) == 0 || ec) {
return false;
}
return true;
}
void run1() // 自动填写操作序列
{
const std::string filePath = "D:/cubeInput.txt";
while (true) {
if (fileHasContent(filePath)) {
// 内容不为空,读取所有行
std::vector<std::string> lines = readAllLines(filePath);
atuoRun(lines);
std::ofstream clear(filePath, std::ios::trunc);
}
// 每隔 500ms 检查一次,避免忙等占用 CPU
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
int main()
{
N = 5;
//test1(); //输入所有操作,只显示最终结果
// test2(); //每次输入1个操作,实时显示结果
run1(); // 自动填写操作序列
return 0;
}
4,case覆盖
对于makeAllEdgeLast里面的U位R位棱组交叉、case1、case2、case3做白盒覆盖:
U位R位棱组交叉对于N=5测不了,只有N是偶数涉及。
case1+case3:
x x z z x z x' z z x x z x' z' x z x' z z x x U F U L U' B U B U B U D B B U U z' x' F3' F R U' R' U F3 F' x' F R' F' D F3' F R U' R' U F3 F' U' x' U' B' D' F3' F R U' R' U F3 U L U' B U B U B U D B B U U R F U R F U y' z' F3' F R U' R' U F3 U L U U B L L U' B U B U B U D B B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' x x U D U' F' U' R U D D U' F F U z' U U F U' F' U' R U U z' U F U' F' U' R U z' U R z F F U F F U' F F y' F R F' y D U' D D U' R' D R D U D U' y' F R F' y D U D' U R' D R D U' D U y' F R F' y D U' D' U U y' F R F' y D U U D D y' F R' F' y D D y' F R F' y U U R' D R D U U D U U y' F R F' y U U y y U' R U' R' U' F' U F U z U' z U' U' L' U L U F U' F' U R U' R' U' F' U F U U z U' z U' U' L' U L U F U' R U R' U' F' U U F R U R' U' R U R' U' F' U F U F' U F U U F' R R F F R' B' R F F R' B R' U R R F F R' B' R F F R' B R' z z U R' U' R U' R' U U R z z F U F' U F U U F'
case2:
U' x x U F U L U' B U B U B U D B B U B L U' z' x' F3' F R U' R' U F3 F' F' U R R L D D F F3' F R U' R' U F3 U L U' B U B U B U D B' L L U' B U B U B U D B B U' R R B U' R B B z z x' F3' F R U' R' U F3 F' x U F F U z F' U' D U R' D R D U y' F R' F' y D D y' F R F' y D U U D U y' F R F' y D U' D' U' y' F R F' y D U D D y' F R' F' y D D y' F R F' y U' y' F R' F' y D D y' F R F' y U y y U z R U' R' U' F' U F z U' z U' z R U' R' U' F' U F z z U R U' R' U' F' U F z z U' L' U L U F U' F' U U z U' z U' z U' U' L' U L U F U' F' z U' L' U L U F U' F' z' U R U' R' U' F' U F z U' U' L' U L U F U' R U R' U' F' U U F R U R' U' R U R' U' F' U U R' U' R U' R' U U R U' R' U' R U' R' U U R U R R F F R' B' R F F R' B R' z z U R' U' R U' R' U U R z z F U F' U F U U F' U U R' U' R U' R' U U R z z F U F' U F U U F' U'
PS:不太好的一点是,代码稍微改一点,就得重新生成用例。

365

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



