模拟:二阶魔方问题

题面:

一个二阶魔方,是一个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;
} 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值