题面:
一个二阶魔方,是一个2×2×2的一个立方体组。立方体由八个角组成。
魔方的每一块都用三维坐标(h, k, l)标记,其中h, k, l∈{0,1}。六个面的每一个都有四个小面,每个小面都有一个正整数。
对于每一步,可以选择一个特定的面,并把此面顺时针或逆时针转90度。
请你判断,是否可以在一个步骤还原这个魔方(每个面没有异色)
输入的第一行包含一个整数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。你可以展开表面以获得平面图如下:
对于每个测试用例,魔方如果可以至多 “只转一步” 恢复,输出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
思路:
- 首先,这道题不要被给定的那一堆坐标迷惑到了,其实他只是告诉你面的顺序罢了。
- 在输入的时候记录一下已完成的面数,如果能够在最多一步内完成魔方的复原,则已经是完成的面的面数只能是两面或者六面。如果不符合可以直接输出NO
- 如果已经完成了六面,那么一定是正确的,直接输出YES即可
- 如果完成了两面,那么我们就开始进行一次判断,一共有24个面,所以可以用一个具有24个元素的数组进行记录
- 可以根据给定的图示做一个小正方体,观察进行一次旋转有可能是那四个数字处于同一面。通过flag来记录是否符合同一颜色的,满足则置为1。
#include<stdio.h>
#include<iostream>
#include<cstring>
using namespace std;
int g[25];
bool met[8];
int main()
{
int N,cnt;
bool flag;
scanf("%d",&N);
while(N--)
{
cnt = 0;
memset(met,false,sizeof(met));
for(int i=1;i<25;i++)
cin>>g[i];
if(g[1]==g[2]&&g[2]==g[3]&&g[3]==g[4])
{
++cnt;
met[0] = 1;
}
if(g[5]==g[6]&&g[6]==g[7]&&g[7]==g[8])
{
++cnt;
met[1] = 1;
}
if(g[9]==g[10]&&g[10]==g[11]&&g[11]==g[12])
{
++cnt;
met[2] = 1;
}
if(g[13]==g[14]&&g[14]==g[15]&&g[15]==g[16])
{
++cnt;
met[3] = 1;
}
if(g[17]==g[18]&&g[18]==g[19]&&g[19]==g[20])
{
++cnt;
met[4] = 1;
}
if(g[21]==g[22]&&g[22]==g[23]&&g[23]==g[24])
{
++cnt;
met[5] = 1;
}
if(cnt==6) cout<<"YES"<<endl;
else if(cnt==2)
{
flag = 0;
if(met[0]&&met[2])
{
if(g[13]==g[14]&&g[13]==g[21]&&g[13]==g[23])
{
if(g[22]==g[24]&&g[22]==g[5]&&g[22]==g[6])
if(g[7]==g[8]&&g[7]==g[18]&&g[7]==g[20])
if(g[17]==g[19]&&g[17]==g[15]&&g[17]==g[16])
flag = 1;
}
else if(g[13]==g[14]&&g[13]==g[18]&&g[13]==g[20])
{
if(g[17]==g[19]&&g[17]==g[5]&&g[17]==g[6])
if(g[7]==g[8]&&g[7]==g[21]&&g[7]==g[23])
if(g[22]==g[24]&&g[22]==g[15]&&g[22]==g[16])
flag = 1;
}
}
else if(met[1] && met[3])
{
if(g[1]==g[2]&&g[1]==g[23]&&g[1]==g[24])
{
if(g[21]==g[22]&&g[21]==g[9]&&g[21]==g[10])
if(g[11]==g[12]&&g[11]==g[19]&&g[11]==g[20])
if(g[17]==g[18]&&g[17]==g[3]&&g[17]==g[4])
flag = 1;
}
else if(g[1]==g[2]&&g[1]==g[19]&&g[1]==g[20])
{
if(g[17]==g[18]&&g[17]==g[9]&&g[17]==g[10])
if(g[11]==g[12]&&g[11]==g[23]&&g[11]==g[24])
if(g[21]==g[22]&&g[21]==g[3]&&g[21]==g[4])
flag = 1;
}
}
else if(met[4] && met[5])
{
if(g[1]==g[3]&&g[1]==g[14]&&g[1]==g[16])
{
if(g[13]==g[15]&&g[13]==g[10]&&g[13]==g[12])
if(g[9]==g[11]&&g[9]==g[6]&&g[9]==g[8])
if(g[5]==g[7]&&g[5]==g[2]&&g[5]==g[4])
flag = 1;
}
else if(g[1]=g[3]&&g[1]==g[6]&&g[1]==g[8])
{
if(g[5]==g[7]&&g[5]==g[10]&&g[5]==g[12])
if(g[9]==g[11]&&g[9]==g[14]&&g[9]==g[16])
if(g[13]==g[15]&&g[13]==g[2]&&g[13]==g[4])
flag = 1;
}
}
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
else cout<<"NO"<<endl;
}
return 0;
}
- 在刚开始看到这道题的时候,我思考的方向是,一个二阶魔方,只可能存在八种可能性(假设魔方处于xyz三维坐标系,则存在绕xy轴顺时针逆时针拧动,由于二阶,所以是八种)
- 然后设定一个用于判断是否当前状态符合魔方复原条件的函数,每次函数处理后都进行判断
- 思考起来非常容易,但是实现的时候很容易绕进去,最后的代码能通过样例和自己出的数据,但是没法通过VJ,应该是某个数转错了(放出这个很长的蒟蒻代码仅用于帮助了解思路,如果有大神能指出错误不胜感激)
#include<iostream>
#include<cstdio>
using namespace std;
int count;
int gezi[25];
bool whether()//判断能否输出
{
count=0;
for(int i=1;i<25;i=i+4)
{
int j=i;
if(gezi[j]==gezi[j+1]&&gezi[j]==gezi[j+2]&&gezi[j]==gezi[j+3])
count++;
}
if(count==6)
return true;
else return false;
}
void xshun1()
{
int temp1=gezi[1];
int temp2=gezi[2];
gezi[1]=gezi[17];
gezi[2]=gezi[18];
gezi[17]=gezi[12];
gezi[18]=gezi[11];
gezi[11]=gezi[22];
gezi[12]=gezi[21];
gezi[21]=temp1;
gezi[22]=temp2;
}
void xshun2()
{
int temp3=gezi[3];
int temp4=gezi[4];
gezi[3]=gezi[19];
gezi[4]=gezi[20];
gezi[19]=gezi[10];
gezi[20]=gezi[9];
gezi[10]=gezi[23];
gezi[9]=gezi[24];
gezi[23]=temp3;
gezi[24]=temp4;
}
void xni1()
{
int temp1=gezi[1];
int temp2=gezi[2];
gezi[1]=gezi[21];
gezi[2]=gezi[22];
gezi[21]=gezi[12];
gezi[22]=gezi[11];
gezi[12]=gezi[17];
gezi[11]=gezi[18];
gezi[17]=temp1;
gezi[18]=temp2;
}
void xni2()
{
int temp3=gezi[3];
int temp4=gezi[4];
gezi[3]=gezi[23];
gezi[4]=gezi[24];
gezi[23]=gezi[10];
gezi[24]=gezi[9];
gezi[10]=gezi[19];
gezi[9]=gezi[20];
gezi[19]=temp3;
gezi[20]=temp4;
}
void yshun1()
{
int temp1=gezi[1];
int temp3=gezi[3];
gezi[1]=gezi[13];
gezi[3]=gezi[15];
gezi[15]=gezi[11];
gezi[13]=gezi[9];
gezi[11]=gezi[7];
gezi[9]=gezi[5];
gezi[5]=temp1;
gezi[7]=temp3;
}
void yshun2()
{
int temp2=gezi[2];
int temp4=gezi[4];
gezi[2]=gezi[14];
gezi[4]=gezi[16];
gezi[14]=gezi[10];
gezi[16]=gezi[12];
gezi[10]=gezi[6];
gezi[12]=gezi[8];
gezi[6]=temp2;
gezi[8]=temp4;
}
void yni1()
{
int temp1=gezi[1];
int temp3=gezi[3];
gezi[1]=gezi[5];
gezi[3]=gezi[7];
gezi[5]=gezi[9];
gezi[7]=gezi[11];
gezi[9]=gezi[13];
gezi[11]=gezi[15];
gezi[13]=temp1;
gezi[15]=temp3;
}
void yni2()
{
int temp2=gezi[2];
int temp4=gezi[4];
gezi[2]=gezi[6];
gezi[4]=gezi[8];
gezi[6]=gezi[10];
gezi[8]=gezi[12];
gezi[10]=gezi[14];
gezi[12]=gezi[16];
gezi[14]=temp2;
gezi[16]=temp4;
}
int main()
{
int N;
scanf("%d",&N);
while(N--)
{
for(int i=1;i<25;i++)
{
cin>>gezi[i];
}
if(whether())//如果现在就稳的一批
{
cout<<"YES"<<endl;
}
else
{
xshun1();
if(whether())
{
cout<<"YES"<<endl;
continue;
}
xshun2();
if(whether())
{
cout<<"YES"<<endl;
continue;
}
xni1();
if(whether())
{
cout<<"YES"<<endl;
continue;
}
xni2();
if(whether())
{
cout<<"YES"<<endl;
continue;
}
yshun1();
if(whether())
{
cout<<"YES"<<endl;
continue;
}
yshun2();
if(whether())
{
cout<<"YES"<<endl;
continue;
}
yni1();
if(whether())
{
cout<<"YES"<<endl;
continue;
}
yni2();
if(whether())
{
cout<<"YES"<<endl;
continue;
}
cout<<"NO"<<endl;
}
}
return 0;
}