题目链接:
Problem Description
小T最近有些疲惫,想找一些能够放松自己的事情去做,正好想起上次被队友用三阶魔方暴杀的经历,就想苦练一下魔方技术,好在下次的对战中击败他的队友。
于是他在网上下单了一个魔方,让小C帮他去取快递。
可是小C有些调皮,私自拆开了快递,随意的扭了这个魔方**不超过三次**(扭的是侧面,不是中间层,且扭的角度固定为90度),还弄掉了**同一个角上的两片贴纸**。
小C的记性不太好,不太记得两片贴纸正确的位置了,所以随意的将两片贴纸贴了回去,并将这件事告诉了小T。
但小T作为一个还在学习如何还原底层十字的小萌新,面对被小C打乱过的魔方很是束手无策。
所以他向你寻求帮助,希望你告诉他小C有没有将两片贴纸正确的贴回去,如果没有的话,是哪一个角的贴纸贴错了呢。
Input
第一行有一个整数,T (1≤T≤10) ,代表数组组数
每组数据输入一个 9 行 12 列的字符型矩阵。
矩阵表示魔方的平面展开图,展开图的格式固定。
输入格式为:
表示一个魔方的平面展开图。
未打乱的魔方为:
"x"在输入的数据中是 [1,6] 中的一个数字,表示这个块原来属于哪一面。
保证所给的魔方至多被扭过三次,且只扭了侧面,没有旋转过中间层。
Output
如果两片贴纸被正确的贴了回去,输出"No problem",否则按升序输出贴错贴纸的角上的三个数字。
Sample Input
2 ***111****** ***111****** ***111****** 223233444555 222333444555 222333444555 ***666****** ***666****** ***666****** ***111****** ***111****** ***111****** 333444555222 222333444555 222333444555 ***666****** ***666****** ***666******
Sample Output
1 2 3
No problem
来源
题目思路
题目要求撕了角块的两张贴纸看是否能还原成原魔方,告诉我们只需要看角块,也就是可以将魔方看为二阶魔方
题目的数据量不大所以可以用暴力枚举,我们只需要列出原魔方的复原形态,再将需要观察的魔方能够得到的各种形态对比,如果能找到一样的形态就输出“No problem”,如果找到和原魔方只差两片的,也只需要将那一块的三个颜色升序输出即可
推导过程
以第一组样例为例子
输入:
***111****** ***111****** ***111****** 223233444555 222333444555 222333444555 ***666****** ***666****** ***666******
输出:
1 2 3(也就是第四行的3和4位置有误)
我们以中心块知道原排列有
如下:
1 3 2 1 4 3 1 5 4 1 2 5
6 2 3 6 3 4 6 4 5 6 5 2
可知1 2 3并不在这些数组里,无论标程中的第三个for如何组合都不会有1 2 3的组合所以直接输出
(如果不够清晰的话可以用以下样例测试:
***111****** ***111****** ***111****** 222333444555 222333444555 222333444655 ***666****** ***666****** ***665****** 遍历的多点更容易理解)
#include<bits/stdc++.h>
using namespace std;
string st[10];
bool vis[1005];//标记出现过的组合
int x[6]= {0,3,3,3,3,6};//与其他数组组合产生x坐标
int y[6]= {3,0,3,6,9,3};//与其他数组组合产生y坐标
int a[8]= {0,0,0,0,5,5,5,5};//与其他数组组合产生每个组合中的第一个颜色
int b[8]= {2,3,4,1,1,2,3,4};//与其他数组组合产生每个组合中的第二个颜色
int c[8]= {1,2,3,4,2,3,4,1};//与其他数组组合产生每个组合中的第三个颜色
int dira[8][2]={2,0,2,2,0,2,0,0,0,0,0,2,2,2,2,0};
int dirb[8][2]={0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2};
int dirc[8][2]={0,2,0,2,0,2,0,2,2,0,2,0,2,0,2,0};
signed main() {
int T;
cin>>T;
while(T--) {
memset(vis,0,sizeof vis);
for(int i=0; i<9; i++)cin>>st[i];
for(int i=0; i<8; i++) {
/*查询当前魔方的形态,思路中提到我们要将魔方看为二阶魔方也就是看它的八个角块
当前的for就是要看我们原来魔方八个角块是什么形态,些角块是对应的
这些可以从每个面的中心块看出来也就是以下代码*/
int A=st[x[a[i]]+1][y[a[i]]+1]-'0';
int B=st[x[b[i]]+1][y[b[i]]+1]-'0';
int C=st[x[c[i]]+1][y[c[i]]+1]-'0';
vis[A*100+B*10+C]=1;
vis[B*100+C*10+A]=1;
vis[C*100+A*10+B]=1;
}
/*
原来魔方能得到的角块形态如下也就是跑for出来的结果
vis
1 3 2
1 4 3
1 5 4
1 2 5
6 2 3
6 3 4
6 4 5
6 5 2
接下来我们只需要找到上面vis数组中没有出现过的组合就行了 */
int flag=1;
for(int i=0; i<8; i++) {
int A=st[x[a[i]]+dira[i][0]][y[a[i]]+dira[i][1]]-'0';
int B=st[x[b[i]]+dirb[i][0]][y[b[i]]+dirb[i][1]]-'0';
int C=st[x[c[i]]+dirc[i][0]][y[c[i]]+dirc[i][1]]-'0';
if(vis[A*100+B*10+C])continue;
flag=0;
int tmp[3]= {A,B,C};
sort(tmp,tmp+3);
cout<<tmp[0]<<" "<<tmp[1]<<" "<<tmp[2]<<endl;
break;
}
if(flag)cout<<"No problem"<<endl;
}
return 0;
}
欢迎讨论