题意:给出一个Pocket Cube的状态,问n步(每步只能顺时针转90度)最多能还原几个面。
思路:作为一个Cuber,看到这种题非常激动,凭着自己对魔方突(yi)破(dian)天(dian)际的理解A掉了。。。这里我用的是dfs+回溯,因为把魔方的状态转成int的哈希不是那么好写,所以没有写状态判重,直接回溯解决。然后,其实六个面的旋转只需要写三个函数,因为相对的面的旋转其实是等效的。
写这个题要非常细心。。因为里面有很多常数。。
#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
#define ll long long
int judge(int* a){
int re=0;
if(a[0]==a[1]&&a[0]==a[2]&&a[0]==a[3])re++;
if(a[4]==a[5]&&a[4]==a[10]&&a[4]==a[11])re++;
if(a[6]==a[7]&&a[6]==a[12]&&a[6]==a[13])re++;
if(a[16]==a[17]&&a[16]==a[18]&&a[16]==a[19])re++;
if(a[8]==a[9]&&a[8]==a[14]&&a[8]==a[15])re++;
if(a[20]==a[21]&&a[20]==a[22]&&a[20]==a[23])re++;
return re;
}
int a[24];
void r(){
int b[24];
memcpy(b,a,sizeof(a));
a[1]=b[7];
a[3]=b[13];
a[7]=b[17];
a[13]=b[19];
a[17]=b[21];
a[19]=b[23];
a[21]=b[1];
a[23]=b[3];
a[8]=b[14];
a[9]=b[8];
a[15]=b[9];
a[14]=b[15];
}
void u(){
int b[24];
memcpy(b,a,sizeof(a));
a[4]=b[6];
a[5]=b[7];
a[6]=b[8];
a[7]=b[9];
a[8]=b[23];
a[9]=b[22];
a[23]=b[4];
a[22]=b[5];
a[0]=b[2];
a[1]=b[0];
a[3]=b[1];
a[2]=b[3];
}
void f(){
int b[24];
memcpy(b,a,sizeof(a));
a[2]=b[11];
a[3]=b[5];
a[8]=b[2];
a[14]=b[3];
a[17]=b[8];
a[16]=b[14];
a[11]=b[17];
a[5]=b[16];
a[6]=b[12];
a[7]=b[6];
a[13]=b[7];
a[12]=b[13];
}
int n;
int ans;
void dfs(int d){
if(d>n||ans==6)return;//剪枝,因为最多6面
ans=max(ans,judge(a));
u();
dfs(d+1);
u(); u(); u();
r();
dfs(d+1);
r(); r(); r();
f();
dfs(d+1);
f(); f(); f();
//相当于d
u(); u(); u();
dfs(d+1);
u();
//相当于l
r(); r(); r();
dfs(d+1);
r();
//相当于b
f(); f(); f();
dfs(d+1);
f();
}
int main(){
while(cin>>n){
ans=0;
for(int i=0;i<24;i++){
scanf("%d",&a[i]);
}
dfs(0);
cout<<ans<<endl;
}
return 0;
}