本文共 4090 字,大约阅读时间需要 13 分钟。
题目
东东有一个二阶魔方,即2×2×2的一个立方体组。立方体由八个角组成。 魔方的每一块都用三维坐标(h, k, l)标记,其中h, k, l∈{0,1}。六个面的每一个都有四个小面,每个小面都有一个正整数。 对于每一步,东东可以选择一个特定的面,并把此面顺时针或逆时针转90度。 请你判断,是否东东可以在一个步骤还原这个魔方(每个面没有异色)。Input
输入的第一行包含一个整数N(N≤30),这是测试用例的数量。对于每个测试用例,
第 1~4 个数描述魔方的顶面,这是常见的2×2面,由(0,0,1),(0,1,1),(1,0,1),(1,1,1)标记。四个整数对应于上述部分。第 5~8 个数描述前面,即(1,0,1),(1,1,1),(1,0,0),(1,1,0)的公共面。四个整数
与上述各部分相对应。第 9~12 个数描述底面,即(1,0,0),(1,1,0),(0,0,0),(0,1,0)的公共面。四个整数与上述各部分相对应。
第 13~16 个数描述背面,即(0,0,0),(0,1,0),(0,0,1),(0,1),(0,1,1)的公共面。四个整数与上述各部分相对应。
第 17~20 个数描述左面,即(0,0,0),(0,0,1),(1,0,0),(1,0,1)的公共面。给出四个整数与上述各部分相对应。
第 21~24 个数描述了右面,即(0,1,1),(0,1,0),(1,1,1),(1,1,0)的公共面。给出四个整数与上述各部分相对应。
换句话说,每个测试用例包含24个整数a、b、c到x。你可以展开表面以获得平面图
如下所示。
Output
对于每个测试用例,魔方如果可以至多 “只转一步” 恢复,输出YES,则输出NO。Sample Input
4 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 6 6 6 6 1 1 1 1 2 2 2 2 3 3 3 3 5 5 5 5 4 4 4 4 1 4 1 4 2 1 2 1 3 2 3 2 4 3 4 3 5 5 5 5 6 6 6 6 1 3 1 3 2 4 2 4 3 1 3 1 4 2 4 2 5 5 5 5 6 6 6 6 Sample Output YES YES YES NO解题过程:首先它是一个魔方(立方体),而且每个面有4个小块,所以建立右手直角坐标系,然后我们发现魔方每次的转动都是有规律的。如下图所示:
那么对于下面的图,我的观察方式为:从上往下看:上面和底面从前往后看:前面和后面从左看左面,从右看右面当然啦,坐标系建立不同,观察角度不同,下图对应的坐标就不相同
那么我为什么要把前后放在一起,上下放在一起,左右放在一起涅?仔细观察,或者想象一下,我转动一个魔方,如果绕z轴旋转,那么它的上面和底面是没有改变的,而每转动一次,不管是逆时针90度,还是顺时针转动90度它的前面无非是转到左面和右面而已,同理可得,绕Y轴旋转的时候,它的前面和后面也是不改变的绕x轴旋转的时候,它的左面和右面也是不改变的
那么看第一部分代码,绕x轴旋转,所以它的前面和后面必须相同,而题目上讲到,前面是第5-8个数,,后面是第13-16个数,把它分成6个面输入,每个面4个小块,所以bool x就是在判断它是否有绕x轴旋转的资本
如果x返回true,则代表前面和后面是无异色的 所以x,y,z就可以写出3个相似的bool函数出来
bool x(){ for(int j=2;j<=4;j+=2) for(int k=2;k<=4;k++) if(a[j][1]!=a[j][k]) return false; return true;}
旋转函数,已经发生了旋转,那么数组元素原先的位置就会发生改变,所以我们要定义一个缓存数组,来存储我们输入的魔方初始值,每一次顺时针旋转后不满足条件,都需要回到初始状态,再进行逆时针旋转
所以产生了如下测试数据:
除了题目本身的数据。这组测试数据涅,是用来判断函数哪一部分出现了差错,我是按照自己写的函数顺序来列的数据: 所有面颜色相同; 绕z轴顺时针旋转,绕z轴逆时针旋转; 绕y轴顺时针旋转,绕y轴逆时针旋转; 绕x轴顺时针旋转,绕x轴逆时针旋转; 每个面各有一种颜色: Input81 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 5 5 2 2 3 3 3 3 4 4 6 6 5 4 5 4 2 6 2 61 1 1 1 6 6 2 2 3 3 3 3 4 4 5 5 5 2 5 2 4 6 4 61 2 1 2 2 3 2 3 3 4 3 4 4 1 4 1 5 5 5 5 6 6 6 61 4 1 4 2 1 2 1 3 2 3 2 4 3 4 3 5 5 5 5 6 6 6 66 6 1 1 2 2 2 2 3 3 5 5 4 4 4 4 1 1 5 5 3 3 6 65 5 1 1 2 2 2 2 3 3 6 6 4 4 4 4 3 3 5 5 1 1 6 61 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6
Output
YESYESYESYESYESYESYESYES
以上数据可以帮助你分别去找代码里的错误
Codes
#includeusing namespace std;int a[7][5],b[7][5];void go_back(){ //回退到输入值 for(int j=1;j<=6;j++) for(int k=1;k<=4;k++) a[j][k]=b[j][k];}//交换函数 void ex(int &s1,int &s2,int &t1,int &t2,int &s3,int &s4,int &t3,int &t4){ int tmp1,tmp2; tmp1=s1;tmp2=s2; s1=t1;s2=t2; t1=s3;t2=s4; s3=t3;s4=t4; t3=tmp1;t4=tmp2;}bool z(){ //绕z轴旋转,那么上面和底面四块颜色已经分别相同 for(int j=1;j<=3;j+=2) for(int k=2;k<=4;k++) if(a[j][1]!=a[j][k]) return false; return true;} bool y(){ //绕y轴旋转,那么左右两面四块颜色已经分别相同 for(int j=5;j<=6;j++) for(int k=2;k<=4;k++) if(a[j][1]!=a[j][k]) return false; return true;}bool x(){ //绕x轴旋转,那么前后两面四块颜色已经分别相同 for(int j=2;j<=4;j+=2) for(int k=2;k<=4;k++) if(a[j][1]!=a[j][k]) return false; return true;}bool spiral(){ //旋转函数 if(z() && !y() && !x()){ ex(a[2][1],a[2][2],a[6][3],a[6][1],a[4][4],a[4][3],a[5][2],a[5][4]); if(z()&&x()&&y()) return true; go_back(); ex(a[2][1],a[2][2],a[5][2],a[5][4],a[4][4],a[4][3],a[6][3],a[6][1]); if(z()&&x()&&y()) return true; return false; } else if(y() && !x() && !z()){ ex(a[2][2],a[2][4],a[1][2],a[1][4],a[4][2],a[4][4],a[3][2],a[3][4]); if(y()&&x()&&z()) return true; go_back(); ex(a[2][2],a[2][4],a[3][2],a[3][4],a[4][2],a[4][4],a[1][2],a[1][4]); if(y()&&x()&&z()) return true; return false; } else if(x() && !y() && !z()){ ex(a[6][1],a[6][2],a[1][1],a[1][2],a[5][1],a[5][2],a[3][4],a[3][3]); if(x()&&z()&&y()) return true; go_back(); ex(a[6][1],a[6][2],a[3][4],a[3][3],a[5][1],a[5][2],a[1][1],a[1][2]); if(x()&&z()&&y()) return true; return false; } return false;}int main(){ int t;cin>>t; while(t--){ for(int j=1;j<=6;j++){ for(int k=1;k<=4;k++){ cin>>a[j][k]; b[j][k]=a[j][k]; } } if(x()&&y()&&z()){ //本身每个面就已经同色 cout<<"YES"<
最后再插一句,那个交换函数一定要用形参,用指针的话会报错,因为
int 和 int*不一样,OK?还有就是直接调用根本不会交换
转载地址:http://tdwzi.baihongyu.com/