(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
目录
题目:传送门
原题目描述在最下面。
结合下面原题目描述的
hint
h
i
n
t
看会比较好理解。
给你一个二阶魔方,问能不能只动一下且只动90°将其复原。(应该都玩过魔方吧
思路:
个人感觉我的写法特别好理解特别好实现,也不是很复杂。
- 首先你要知道你动一下只有六种不同性质的操作。(左边向上划和向下划,上面向左划和向下划,前面向左划和向右划)
- 然后把每种操作影响到的块的数字编号处理出来,请看结合代码和图片。
- 动一下,相当于颜色交错两位。就这样进行旋转操作。
- 因为只有六种操作,你就每操作一次后判断一下,若不合法就复原上一次的样子
- 复原上一次的样子就执行相反操作就好了。
AC代码:
#include<bits/stdc++.h>
#define lowbit(x) (x&(-(x)))
#define mme(a,b) memset((a),(b),sizeof((a)))
#define fuck(x) cout<<"* "<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
const int N = 1e6 + 7;
const int ME = 1e6 + 7;
const int mod = 998244353;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
typedef pair<int,int> pii;
int n;
int ar[N];
int op[6][8]={
{11,9,7,5,3,1,22,24},//左上
{24,22,1,3,5,7,9,11},//左下
{11,12,20,18,2,1,13,15},//上左
{15,13,1,2,18,20,12,11},//上右
{24,23,20,19,8,7,16,15},//前左
{15,16,7,8,19,20,23,24},//前右
};
int opt[6]={//每个操作对应相反操作的编号
1,0,3,2,5,4
};
int gao(int x){//旋转操作
int aa = ar[op[x][0]];
int bb = ar[op[x][1]];
for(int i=0;i<5;i+=2){
ar[op[x][i]]=ar[op[x][i+2]];
ar[op[x][i+1]]=ar[op[x][i+3]];
}
ar[op[x][6]]=aa;
ar[op[x][7]]=bb;
}
bool ok(){
int haha=0;
for(int i=1;i<=21;i+=4){//每四个一组为一面,共六面
if(ar[i]==ar[i+1]&&ar[i]==ar[i+2]&&ar[i]==ar[i+3])haha=1;
else return false;
}
return true;
}
int main(){
for(int i=1;i<=24;++i){
scanf("%d", &ar[i]);
}
int flag=0;
for(int i=0;i<6;++i){
gao(i);//操作它
if(ok())flag=1;//魔方成功还原
gao(opt[i]);//返回原始样子
}
if(flag)printf("YES\n");
else printf("NO\n");
return 0;
}