1. 题目描述
给定一个$2 \times 2 \times 2$的魔方,当某个面上的4个小块颜色均相同时,称这个面为complete。求对这个魔方进行$n \in [1,7]$次旋转(沿某个面顺时针或者逆时针)的过程中,求complete的面总和的最大值。魔方及索引如下图所示:
2. 基本思路及代码
解法一(MLE):
刚读过题,觉得挺简单的,时限10000ms还挺长的。需要搞清楚沿着某个面旋转后矩阵的元素是如何变化的。
就想到可以进行状态压缩$6^24 < 2^63$,因此将cube表示的矩阵可以使用long long压缩状态,然后再带上已经旋转的次数作为key,记忆化搜索就好了。代码如下:
1 /* 4801 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <bitset> 12 #include <algorithm> 13 #include <cstdio> 14 #include <cmath> 15 #include <ctime> 16 #include <cstring> 17 #include <climits> 18 #include <cctype> 19 #include <cassert> 20 #include <functional> 21 #include <iterator> 22 #include <iomanip> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,1024000") 25 26 #define sti set<int> 27 #define stpii set<pair<int, int> > 28 #define mpii map<int,int> 29 #define vi vector<int> 30 #define pii pair<int,int> 31 #define vpii vector<pair<int,int> > 32 #define rep(i, a, n) for (int i=a;i<n;++i) 33 #define per(i, a, n) for (int i=n-1;i>=a;--i) 34 #define clr clear 35 #define pb push_back 36 #define mp make_pair 37 #define fir first 38 #define sec second 39 #define all(x) (x).begin(),(x).end() 40 #define SZ(x) ((int)(x).size()) 41 #define lson l, mid, rt<<1 42 #define rson mid+1, r, rt<<1|1 43 44 #define LL __int64 45 46 typedef struct { 47 int st, t; 48 } node_t; 49 50 map<pair<LL,int>, int> tb; 51 map<pair<LL,int>, int>::iterator iter; 52 LL mask[24]; 53 int a[24]; 54 int n; 55 int face[6][4] = { 56 {0, 1, 2, 3}, 57 {4, 5, 10, 11}, 58 {6, 7, 12, 13}, 59 {8, 9, 14, 15}, 60 {16, 17, 18, 19}, 61 {20, 21, 22, 23} 62 }; 63 64 int movf[6][12] = { 65 {0,1,3,2, 22,23,9,8,7,6,5,4}, 66 {18,19,17,16, 20,21,15,14,13,12,11,10,}, 67 {4,5,11,10, 0,2,6,12,16,18,20,22}, 68 {9,8,14,15, 1,3,7,13,17,19,21,23}, 69 {6,7,12,13, 2,3,8,14,17,16,11,5}, 70 {22,23,21,20, 0,1,9,15,19,18,10,4} 71 }; 72 int nxt[4]; 73 int unxt[4]; 74 75 void init() { 76 mask[0] = 3; 77 rep(i, 1, 24) 78 mask[i] = mask[i-1] << 2; 79 80 rep(i, 0, 4) { 81 nxt[i] = (i+1) % 4; 82 unxt[i] = (i-1+4)%4; 83 } 84 } 85 86 LL zip(int *a) { 87 LL ret = 0; 88 89 per(i, 0, 24) 90 ret = ret*6 + a[i]; 91 92 return ret; 93 } 94 95 void unzip(LL val, int *a) { 96 rep(i, 0, 24) { 97 a[i] = val % 6; 98 val /= 6; 99 } 100 } 101 102 int calc(LL st) { 103 static int b[24]; 104 int ret = 0; 105 unzip(st, b); 106 107 rep(i, 0, 6) { 108 ++ret; 109 rep(j, 1, 4) { 110 if (b[face[i][j]] != b[face[i][0]]) { 111 --ret; 112 break; 113 } 114 } 115 } 116 117 return ret; 118 } 119 120 LL move_clock(LL st, int id) { 121 static int b[24]; 122 static int c[24]; 123 int i, j, *mf = movf[id]; 124 125 unzip(st, b); 126 memcpy(c, b, sizeof(c)); 127 128 for (i=0; i<4; ++i) 129 c[mf[nxt[i]]] = b[mf[i]]; 130 for (i=0; i<4; ++i) { 131 c[mf[(nxt[i]<<1)+4]] = b[mf[(i<<1)+4]]; 132 c[mf[(nxt[i]<<1|1)+4]] = b[mf[(i<<1|1)+4]]; 133 } 134 135 return zip(c); 136 } 137 138 LL move_unclock(LL st, int id) { 139 static int b[24]; 140 static int c[24]; 141 int i, j, *mf = movf[id]; 142 143 unzip(st, b); 144 memcpy(c, b, sizeof(c)); 145 146 for (i=0; i<4; ++i) 147 c[mf[unxt[i]]] = b[mf[i]]; 148 for (i=0; i<4; ++i) { 149 c[mf[(unxt[i]<<1)+4]] = b[mf[(i<<1)+4]]; 150 c[mf[(unxt[i]<<1|1)+4]] = b[mf[(i<<1|1)+4]]; 151 } 152 153 return zip(c); 154 } 155 156 157 int dfs(LL st, int n) { 158 pair<LL,int> p = mp(st, n); 159 160 iter = tb.find(p); 161 if (iter != tb.end()) 162 return iter->sec; 163 164 int ret = 0; 165 166 ret = calc(st); 167 168 LL nst; 169 170 #ifndef ONLINE_JUDGE 171 int b[24]; 172 #endif 173 174 if (n) { 175 rep(i, 0, 6) { 176 nst = move_clock(st, i); 177 #ifndef ONLINE_JUDGE 178 unzip(nst, b); 179 rep(j, 0, 24) 180 printf("%d ", b[j]); 181 putchar('\n'); 182 #endif 183 ret = max(ret, dfs(nst, n-1)); 184 nst = move_unclock(st, i); 185 #ifndef ONLINE_JUDGE 186 unzip(nst, b); 187 rep(j, 0, 24) 188 printf("%d ", b[j]); 189 putchar('\n'); 190 #endif 191 ret = max(ret, dfs(nst, n-1)); 192 } 193 } 194 195 tb[p] = ret; 196 197 return ret; 198 } 199 200 void solve() { 201 LL st = zip(a); 202 int ans = 0; 203 204 // tb.clr(); 205 206 ans = dfs(st, n); 207 208 printf("%d\n", ans); 209 } 210 211 int main() { 212 ios::sync_with_stdio(false); 213 #ifndef ONLINE_JUDGE 214 freopen("data.in", "r", stdin); 215 freopen("data.out", "w", stdout); 216 #endif 217 218 init(); 219 while (scanf("%d", &n)!=EOF) { 220 rep(i, 0, 24) 221 scanf("%d", &a[i]); 222 solve(); 223 } 224 225 #ifndef ONLINE_JUDGE 226 printf("time = %d.\n", (int)clock()); 227 #endif 228 229 return 0; 230 }