题目链接

模拟

模拟题 魔方的旋转是难点,比较繁琐。 下面这个方法是我目前觉得比较不容易出错的方法,做魔方的旋转。 假设当前的魔方用一个数组记录为cur[24]

预处理出一个Next数组,给当前数组的位置做重排。
用一个新数组 New[24]记录重排后的魔方, New[i] = cur[Next[j]] 表示的是旋转后的魔方第i个位置是先前魔方Next[j]这个位置的数。预处理出六种旋转方式,用Next[6][24]存储,在做变化的时候,用上面的方法得到一个变化后的魔方New

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>

using namespace std;

const int Maxn = 2e5+10;
const long long LINF = 1e18;
const double eps = 1e-6;

int N, ans;
char str[30];

int Next[10][30] = {
					{0,21,2,23,4,5,6,1,9,15,10,11,12,3,8,14,16,7,18,13,20,17,22,19}, // 右面顺时针 
					{0,7,2,13,4,5,6,17,14,8,10,11,12,19,15,9,16,21,18,23,20,1,22,3}, // 右面逆时针 
					{0,1,2,3,4,5,6,7,8,9,12,13,14,15,21,20,17,19,16,18,11,10,22,23}, // 前面顺时针 
					{0,1,2,3,4,5,6,7,8,9,21,20,10,11,12,13,18,16,19,17,15,14,22,23}, // 前面逆时针 
					{0,1,11,5,4,16,12,6,2,9,10,17,13,7,3,15,14,8,18,19,20,21,22,23}, // 底面顺时针 
					{0,1,8,14,4,3,7,13,17,9,10,2,6,12,16,15,5,11,18,19,20,21,22,23}  // 底面逆时针 
};

int check(char *ss) {
	int cnt = 0;
	if(ss[0] == ss[1] && ss[1] == ss[2] && ss[2] == ss[3]) cnt++;
	if(ss[4] == ss[5] && ss[5] == ss[10] && ss[10] == ss[11]) cnt++;
	if(ss[6] == ss[7] && ss[7] == ss[12] && ss[12] == ss[13]) cnt++;
	if(ss[8] == ss[9] && ss[9] == ss[14] && ss[14] == ss[15]) cnt++;
	if(ss[16] == ss[17] && ss[17] == ss[18] && ss[18] == ss[19]) cnt++;
	if(ss[20] == ss[21] && ss[21] == ss[22] && ss[22] == ss[23]) cnt++;
	return cnt;
}


void dfs(char *ss, int step, int last) {
	if(step > N) return;
	ans = max(ans, check(ss));
	if(ans == 6) return;
	char tmp[30];
	for(int i = 0; i < 6; ++i) {
		if(i == last) continue;
		for(int j = 0; j < 24; ++j) tmp[j] = ss[Next[i][j]];
		dfs(tmp, step+1, i^1);
		if(ans == 6) return;
	}
}

int main(void)
{
	while(scanf("%d", &N) != EOF) {
		int x;
		for(int i = 0; i < 24; ++i) {
			scanf("%d", &x);
			str[i] = x+'0';	
		}
		str[24] = '\0';
		ans = 0;
		dfs(str, 0, -1);
		printf("%d\n", ans);
	}
	return 0;
 }