绝对不模拟的简单魔方
Tag:观察题
题目描述
先不描述了 后面有机会补
分析
首先一定要记住, 这个题不会旋转中间块, 就是说所有面的中心块是固定的,意味着每一个面的正确颜色是固定的, 后续的所有分析都建立在这个基础之上。
首先玩过魔方的都知道,如果对于一个正常的魔方, 我们旋转了它的一个角块之后, 这个魔方是无法被复原的。
思考一下这道题和旋转了角块的区别是什么, 如果我们做的是旋转角块, 那么我们强制把这个角块其中一个颜色匹配到正确的位置, 这个时候角块剩下的两个颜色一定是匹配的。
那么这个题给出的条件是有可能交换了一个角块的其中两个颜色, 如果我们按照上面说的, 我们强制匹配这个角块中的一个颜色, 那么另外两个颜色是无论如何都匹配不上的。
我们可以把上面这个东西转化成一个序列来理解, 假设我们一开始有一个序列为 \(\{1,2,3\}\), 那么很明显, 我们可以把这个序列进行平移操作成 \(\{3,1,2\}\) 和 \(\{2,3,1\}\)。 如果我们把序列 \(\{1,2,3\}\) 中的两个元素交换一下, 把序列变成 \(\{1,3,2\}\), 那么我们对这个序列平移可以得到 \(\{2,1,3\}\) 和 \(\{3,2,1\}\)。 我们会发现,如果我们交换了一个序列里的两个数字, 那么平移出来的序列都是不一样的。
我们把上述的序列转化成颜色,放到魔方上来理解, 也就是说对于每一个平面来说,我们可以按照固定的顺序来访问一个角块链接的三个平面, 由此来得到八个正确的颜色序列。 之后我们按照我们刚才访问平面的顺序,去记录每一个角块的颜色构成, 就得到了8个角块的颜色序列。 我们对于每一个角块的颜色序列进行平移,一共可以得出三个颜色序列, 按照上文所说的,如果这三个序列中有一个和正确的颜色序列匹配上了, 那么这个角块就是正确的。 所以我们只需要遍历八个角块的颜色序列,对于每个序列平移两次, 检查在正确的颜色序列中是否存在这样的颜色序列, 如果存在一个角块,他的颜色在旋转之后无法和任何一个序列进行匹配, 那么这个角块就是被交换了颜色的角块。
一定要注意,上面提到的按照顺序, 一定要访问角块的顺序和访问面的顺序是一样的, 至于为什么,留给读者自行思考。
附上我赛时思考画的图,其中记录了角块的访问必须是按顺序的,以及魔方的展开, 不过我在写代码的时候一开始写乱了后改的, 所以代码里的角块访问顺序和我画的图不一定一样。
代码写的非常乱,大家可以观察仔细部分思考明白了自己画图进行序列的插入。
如果理解不了我上文的旋转角块部分以及匹配部分可以自己买一个魔方把玩一下。
代码实现
void NeverSayNever() {
int cube[10][13];
for (int i = 1; i <= 9; ++i) {
string tmp; cin >> tmp;
tmp = " " + tmp;
for (int j = 1; j <= 12; ++j) {
if(tmp[j] == '*'){
cube[i][j] = 0;
}else{
cube[i][j] = tmp[j] - '0';
}
}
}
set<deque<int>> st;
st.insert({1, 3, 2});
st.insert({5, 2, 6});
st.insert({4, 5, 6});
st.insert({4, 3, 1});
st.insert({6, 3, 4});
st.insert({1, 5, 4});
st.insert({2, 3, 6});
st.insert({1, 2, 5});
vector<deque<int>> tmp;
tmp.push_back({cube[6][9], cube[6][10], cube[9][6]});
tmp.push_back({cube[4][7], cube[4][6], cube[3][6]});
tmp.push_back({cube[6][12], cube[6][1], cube[9][4]});
tmp.push_back({cube[3][4], cube[4][4], cube[4][3]});
tmp.push_back({cube[1][6], cube[4][10], cube[4][9]});
tmp.push_back({cube[1][4], cube[4][1], cube[4][12]});
tmp.push_back({cube[7][6], cube[6][6], cube[6][7]});
tmp.push_back({cube[6][3], cube[6][4], cube[7][4]});
auto check = [&](deque<int> & dq)->bool{
for (int i = 0; i < 2; ++i) {
if(st.contains(dq)){
return true;
}
dq.push_front(dq.back());
dq.pop_back();
}
if(st.contains(dq)){
return true;
}
return false;
};
for (int i = 0; i < tmp.size(); ++i) {
if(check(tmp[i]) == false){
std::sort(tmp[i].begin(), tmp[i].end());
cout << tmp[i][0] << ' ' << tmp[i][1] << ' ' << tmp[i][2] << endl;
return;
}
}
cout << "No problem" << endl;
}
额外思考
套着大模拟外表的观察题。
日志
本页面创建于 2024/7/22 17:01