【HDOJ】4801 Pocket Cube 的几种解法和优化

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 }
View Code

交了一下,果断MLE了。分析为什么?显然状态太多了,因为同一个魔方因为摆放位置不同,表示的数组也不同,导致状态太多,记忆化搜索时存的东西太多。

解法二(TLE):
因为$n$很小,所以果断去掉了记忆化的map,抱着$n$很小但时限很长的侥幸心理,试试。

  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 int a[24];
 47 int n;
 48 int face[6][4] = {
 49     {0, 1, 2, 3},
 50     {4, 5, 10, 11},
 51     {6, 7, 12, 13},
 52     {8, 9, 14, 15},
 53     {16, 17, 18, 19},
 54     {20, 21, 22, 23}
 55 };
 56 
 57 int movf[6][12] = {
 58     {0,1,3,2,         22,23,9,8,7,6,5,4},
 59     {18,19,17,16,     20,21,15,14,13,12,11,10,},
 60     {4,5,11,10,        0,2,6,12,16,18,20,22},
 61     {9,8,14,15,        1,3,7,13,17,19,21,23},
 62     {6,7,12,13,        2,3,8,14,17,16,11,5},
 63     {22,23,21,20,    0,1,9,15,19,18,10,4}
 64 };
 65 int nxt[4];
 66 int unxt[4];
 67 
 68 void init() {
 69     rep(i, 0, 4) {
 70         nxt[i] = (i+1) % 4;
 71         unxt[i] = (i-1+4)%4;
 72     }
 73 }
 74 
 75 LL zip(int *a) {
 76     LL ret = 0;
 77 
 78     per(i, 0, 24)
 79         ret = ret*6 + a[i];
 80 
 81     return ret;
 82 }
 83 
 84 void unzip(LL val, int *a) {
 85     rep(i, 0, 24) {
 86         a[i] = val % 6;
 87         val /= 6;
 88     }
 89 }
 90 
 91 int calc(LL st) {
 92     static int b[24];
 93     int ret = 0;
 94     unzip(st, b);
 95 
 96     rep(i, 0, 6) {
 97         ++ret;
 98         rep(j, 1, 4) {
 99             if (b[face[i][j]] != b[face[i][0]]) {
100                 --ret;
101                 break;
102             }
103         }
104     }
105 
106     return ret;
107 }
108 
109 LL move_clock(LL st, int id) {
110     static int b[24];
111     static int c[24];
112     int i, j, *mf = movf[id];
113 
114     unzip(st, b);
115     memcpy(c, b, sizeof(c));
116 
117     for (i=0; i<4; ++i)
118         c[mf[nxt[i]]] = b[mf[i]];
119     for (i=0; i<4; ++i) {
120         c[mf[(nxt[i]<<1)+4]] = b[mf[(i<<1)+4]];
121         c[mf[(nxt[i]<<1|1)+4]] = b[mf[(i<<1|1)+4]];
122     }
123 
124     return zip(c);
125 }
126 
127 LL move_unclock(LL st, int id) {
128     static int b[24];
129     static int c[24];
130     int i, j, *mf = movf[id];
131 
132     unzip(st, b);
133     memcpy(c, b, sizeof(c));
134 
135     for (i=0; i<4; ++i)
136         c[mf[unxt[i]]] = b[mf[i]];
137     for (i=0; i<4; ++i) {
138         c[mf[(unxt[i]<<1)+4]] = b[mf[(i<<1)+4]];
139         c[mf[(unxt[i]<<1|1)+4]] = b[mf[(i<<1|1)+4]];
140     }
141 
142     return zip(c);
143 }
144 
145 
146 int dfs(LL st, int n) {
147     int ret = 0;
148     
149     ret = calc(st);
150     
151     LL nst;
152     
153     if (n) {
154         rep(i, 0, 6) {
155             nst = move_clock(st, i);
156             ret = max(ret, dfs(nst, n-1));
157             nst = move_unclock(st, i);
158             ret = max(ret, dfs(nst, n-1));
159         }
160     }
161 
162     return ret;
163 }
164 
165 void solve() {
166     LL st = zip(a);
167     int ans = 0;
168 
169     ans = dfs(st, n);
170 
171     printf("%d\n", ans);
172 }
173 
174 int main() {
175     ios::sync_with_stdio(false);
176     #ifndef ONLINE_JUDGE
177         freopen("data.in", "r", stdin);
178         freopen("data.out", "w", stdout);
179     #endif
180 
181     init();
182     while (scanf("%d", &n)!=EOF) {
183         rep(i, 0, 24)
184             scanf("%d", &a[i]);
185         solve();
186     }
187 
188     #ifndef ONLINE_JUDGE
189         printf("time = %d.\n", (int)clock());
190     #endif
191 
192     return 0;
193 }
View Code

果断TLE了。分析为什么?最坏情况下深搜的深度为7,每次深搜有12种旋转方式($6 \text{ faces } \times 2 \text{ directions }$)。
这棵搜索树的毛病太多了:结点太多($12^7 = 35831808$),存储消耗的也厉害。怎么办?

解法三(AC 717ms):
显然需要尽可能的减少旋转方式,观察6个面,两两相对。不妨令$F_a$与$F_b$相对,观察和想象可以发现对$F_a$进行顺时针旋转和对$F_b$进行逆时针旋转得到是相同配置的魔方。这样我们可以将旋转方式减少到6种,$6^7 = 279936$已经足够小了。这次果然AC,时间717ms,说明数据还是比较小的。

  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 int a[24];
 47 int n;
 48 int face[6][4] = {
 49     {0, 1, 2, 3},
 50     {4, 5, 10, 11},
 51     {6, 7, 12, 13},
 52     {8, 9, 14, 15},
 53     {16, 17, 18, 19},
 54     {20, 21, 22, 23}
 55 };
 56 
 57 int movf[3][12] = {
 58     {0,1,3,2,         22,23,9,8,7,6,5,4},
 59     // {18,19,17,16,     20,21,15,14,13,12,11,10,},
 60     {4,5,11,10,        0,2,6,12,16,18,20,22},
 61     // {9,8,14,15,        1,3,7,13,17,19,21,23},
 62     {6,7,13,12,        2,3,8,14,17,16,11,5}
 63     // {22,23,21,20,      0,1,9,15,19,18,10,4},
 64 };
 65 int movp[6][24];
 66 int nxt[4];
 67 int unxt[4];
 68 int ans;
 69 
 70 void init() {
 71     rep(i, 0, 4) {
 72         nxt[i] = (i+1) % 4;
 73         unxt[i] = (i-1+4)%4;
 74     }
 75     
 76     int i, j, k;
 77     for (k=0,j=0; k<3; ++k,j+=2) {
 78         int *mf = movf[k];
 79         int *c = movp[j];
 80         for (i=0; i<24; ++i)    c[i] = i;
 81         for (i=0; i<4; ++i)
 82             c[mf[nxt[i]]] = mf[i];
 83         for (i=0; i<4; ++i) {
 84             c[mf[(nxt[i]<<1)+4]] = mf[(i<<1)+4];
 85             c[mf[(nxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 86         }
 87         
 88         c = movp[j+1];
 89         for (i=0; i<24; ++i)    c[i] = i;
 90         for (i=0; i<4; ++i)
 91             c[mf[unxt[i]]] = mf[i];
 92         for (i=0; i<4; ++i) {
 93             c[mf[(unxt[i]<<1)+4]] = mf[(i<<1)+4];
 94             c[mf[(unxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 95         }
 96     }
 97 }
 98 
 99 int calc(int *b) {
100     int ret = 0;
101 
102     rep(i, 0, 6) {
103         ++ret;
104         rep(j, 1, 4) {
105             if (b[face[i][j]] != b[face[i][0]]) {
106                 --ret;
107                 break;
108             }
109         }
110     }
111 
112     return ret;
113 }
114 
115 inline void move(int *b, int *c, int id) {
116     int i;
117     
118     for (i=0; i<24; ++i)    c[i] = b[movp[id][i]];
119 }
120 
121 void dfs(int *a, int n) {
122     int b[24];
123     
124     ans = max(ans, calc(a));
125     
126     if (n) {
127         rep(i, 0, 6) {
128             move(a, b, i);
129             dfs(b, n-1);
130         }
131     }
132 }
133 
134 void solve() {
135     ans = 0;
136 
137     dfs(a, n);
138 
139     printf("%d\n", ans);
140 }
141 
142 int main() {
143     ios::sync_with_stdio(false);
144     #ifndef ONLINE_JUDGE
145         freopen("data.in", "r", stdin);
146         freopen("data.out", "w", stdout);
147     #endif
148 
149     init();
150     while (scanf("%d", &n)!=EOF) {
151         rep(i, 0, 24)
152             scanf("%d", &a[i]);
153         solve();
154     }
155 
156     #ifndef ONLINE_JUDGE
157         printf("time = %d.\n", (int)clock());
158     #endif
159 
160     return 0;
161 }
View Code


解法四(AC 265ms):
能不能再优化?为了优化这个深搜,显然要剪枝。基本思路是启发式函数或者剪掉重复状态。没想到太好的启发函数,因此思考能不能对已经出现的配置的魔方不再进行深搜(类似于方法一的记忆化搜索)。考虑对同一个面先顺时针旋转后立即进行逆时针旋转是没有意义的,因此这个可以剪枝。将717ms优化到265ms,效果还不错。

  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 int a[24];
 47 int n;
 48 int face[6][4] = {
 49     {0, 1, 2, 3},
 50     {4, 5, 10, 11},
 51     {6, 7, 12, 13},
 52     {8, 9, 14, 15},
 53     {16, 17, 18, 19},
 54     {20, 21, 22, 23}
 55 };
 56 
 57 int movf[3][12] = {
 58     {0,1,3,2,         22,23,9,8,7,6,5,4},
 59     // {18,19,17,16,     20,21,15,14,13,12,11,10,},
 60     {4,5,11,10,        0,2,6,12,16,18,20,22},
 61     // {9,8,14,15,        1,3,7,13,17,19,21,23},
 62     {6,7,13,12,        2,3,8,14,17,16,11,5}
 63     // {22,23,21,20,      0,1,9,15,19,18,10,4},
 64 };
 65 int movp[6][24];
 66 int nxt[4];
 67 int unxt[4];
 68 int ans;
 69 
 70 void init() {
 71     rep(i, 0, 4) {
 72         nxt[i] = (i+1) % 4;
 73         unxt[i] = (i-1+4)%4;
 74     }
 75     
 76     int i, j, k;
 77     for (k=0,j=0; k<3; ++k,j+=2) {
 78         int *mf = movf[k];
 79         int *c = movp[j];
 80         for (i=0; i<24; ++i)    c[i] = i;
 81         for (i=0; i<4; ++i)
 82             c[mf[nxt[i]]] = mf[i];
 83         for (i=0; i<4; ++i) {
 84             c[mf[(nxt[i]<<1)+4]] = mf[(i<<1)+4];
 85             c[mf[(nxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 86         }
 87         
 88         c = movp[j+1];
 89         for (i=0; i<24; ++i)    c[i] = i;
 90         for (i=0; i<4; ++i)
 91             c[mf[unxt[i]]] = mf[i];
 92         for (i=0; i<4; ++i) {
 93             c[mf[(unxt[i]<<1)+4]] = mf[(i<<1)+4];
 94             c[mf[(unxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 95         }
 96     }
 97 }
 98 
 99 int calc(int *b) {
100     int ret = 0;
101 
102     rep(i, 0, 6) {
103         ++ret;
104         rep(j, 1, 4) {
105             if (b[face[i][j]] != b[face[i][0]]) {
106                 --ret;
107                 break;
108             }
109         }
110     }
111 
112     return ret;
113 }
114 
115 inline void move(int *b, int *c, int id) {
116     int i;
117     
118     for (i=0; i<24; ++i)    c[i] = b[movp[id][i]];
119 }
120 
121 void dfs(int *a, int n, int pre) {
122     int b[24];
123     
124     ans = max(ans, calc(a));
125     
126     if (n) {
127         rep(i, 0, 6) {
128             if ((i^1) == pre)
129                 continue;
130             move(a, b, i);
131             dfs(b, n-1, i);
132         }
133     }
134 }
135 
136 void solve() {
137     ans = 0;
138 
139     dfs(a, n, -1);
140 
141     printf("%d\n", ans);
142 }
143 
144 int main() {
145     ios::sync_with_stdio(false);
146     #ifndef ONLINE_JUDGE
147         freopen("data.in", "r", stdin);
148         freopen("data.out", "w", stdout);
149     #endif
150 
151     init();
152     while (scanf("%d", &n)!=EOF) {
153         rep(i, 0, 24)
154             scanf("%d", &a[i]);
155         solve();
156     }
157 
158     #ifndef ONLINE_JUDGE
159         printf("time = %d.\n", (int)clock());
160     #endif
161 
162     return 0;
163 }
View Code


解法五(AC 265ms):
还能不能继续剪枝?显然可以,对同一个面连续进行超过2次顺时针旋转或逆时针旋转没有任何意义,因为都可以通过更少次数的相反方向旋转实现。
然而,加上这个剪枝并没有什么提高,还能不能更快?

  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 int a[24];
 47 int n;
 48 int face[6][4] = {
 49     {0, 1, 2, 3},
 50     {4, 5, 10, 11},
 51     {6, 7, 12, 13},
 52     {8, 9, 14, 15},
 53     {16, 17, 18, 19},
 54     {20, 21, 22, 23}
 55 };
 56 
 57 int movf[3][12] = {
 58     {0,1,3,2,         22,23,9,8,7,6,5,4},
 59     {4,5,11,10,        0,2,6,12,16,18,20,22},
 60     {6,7,13,12,        2,3,8,14,17,16,11,5}
 61 };
 62 int movp[6][24];
 63 int nxt[4];
 64 int unxt[4];
 65 int ans;
 66 
 67 void init() {
 68     rep(i, 0, 4) {
 69         nxt[i] = (i+1) % 4;
 70         unxt[i] = (i-1+4)%4;
 71     }
 72     
 73     int i, j, k;
 74     for (k=0,j=0; k<3; ++k,j+=2) {
 75         int *mf = movf[k];
 76         int *c = movp[j];
 77         for (i=0; i<24; ++i)    c[i] = i;
 78         for (i=0; i<4; ++i)
 79             c[mf[nxt[i]]] = mf[i];
 80         for (i=0; i<4; ++i) {
 81             c[mf[(nxt[i]<<1)+4]] = mf[(i<<1)+4];
 82             c[mf[(nxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 83         }
 84         
 85         c = movp[j+1];
 86         for (i=0; i<24; ++i)    c[i] = i;
 87         for (i=0; i<4; ++i)
 88             c[mf[unxt[i]]] = mf[i];
 89         for (i=0; i<4; ++i) {
 90             c[mf[(unxt[i]<<1)+4]] = mf[(i<<1)+4];
 91             c[mf[(unxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 92         }
 93     }
 94 }
 95 
 96 int calc(int *b) {
 97     int ret = 0;
 98 
 99     rep(i, 0, 6) {
100         ++ret;
101         rep(j, 1, 4) {
102             if (b[face[i][j]] != b[face[i][0]]) {
103                 --ret;
104                 break;
105             }
106         }
107     }
108 
109     return ret;
110 }
111 
112 inline void move(int *b, int *c, int id) {
113     int i;
114     
115     for (i=0; i<24; ++i)    c[i] = b[movp[id][i]];
116 }
117 
118 void dfs(int *a, int n, int pre, int deep) {
119     int b[24];
120     
121     ans = max(ans, calc(a));
122     
123     if (n) {
124         rep(i, 0, 6) {
125             if ((i^1) == pre)
126                 continue;
127             if (i != pre) {
128                 move(a, b, i);
129                 dfs(b, n-1, i, 1);
130             } else if (deep < 2) {
131                 move(a, b, i);
132                 dfs(b, n-1, i, deep+1);
133             }
134         }
135     }
136 }
137 
138 void solve() {
139     ans = 0;
140 
141     dfs(a, n, -1, 0);
142 
143     printf("%d\n", ans);
144 }
145 
146 int main() {
147     ios::sync_with_stdio(false);
148     #ifndef ONLINE_JUDGE
149         freopen("data.in", "r", stdin);
150         freopen("data.out", "w", stdout);
151     #endif
152 
153     init();
154     while (scanf("%d", &n)!=EOF) {
155         rep(i, 0, 24)
156             scanf("%d", &a[i]);
157         solve();
158     }
159 
160     #ifndef ONLINE_JUDGE
161         printf("time = %d.\n", (int)clock());
162     #endif
163 
164     return 0;
165 }
View Code


解法六(AC 234ms):
将问题转化,即$n$次旋转可以想象为长度为$n$的$[0,5]$的任意排列,当然这个排列中有些是可以被剪枝的。比如,形如$*F_aF_aF_a*$,或者$*F_aF_b*$。然而,无论魔方初始的配置是什么样的,旋转就是数组中的某些元素交换位置,因此可以预处理进行$[0,7]$次旋转后,数组中元素位置的排列。这个预处理,直接深搜就好了。果然,略微有所优化。

  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     char a[24];
 48 } node_t;
 49 
 50 int a[24], b[24];
 51 int n;
 52 int face[6][4] = {
 53     {0, 1, 2, 3},
 54     {4, 5, 10, 11},
 55     {6, 7, 12, 13},
 56     {8, 9, 14, 15},
 57     {16, 17, 18, 19},
 58     {20, 21, 22, 23}
 59 };
 60 
 61 int movf[3][12] = {
 62     {0,1,3,2,         22,23,9,8,7,6,5,4},
 63     {4,5,11,10,        0,2,6,12,16,18,20,22},
 64     {6,7,13,12,        2,3,8,14,17,16,11,5}
 65 };
 66 int movp[6][24];
 67 int nxt[4];
 68 int unxt[4];
 69 int ans;
 70 vector<node_t> vc[8];
 71 
 72 void dfs(node_t nd, int step, int pre, int deep) {
 73     vc[step].pb(nd);
 74     
 75     node_t d;
 76     
 77     if (step < 7) {
 78         rep(i, 0, 6) {
 79             if ((i^1) == pre)
 80                 continue;
 81             if (i != pre) {
 82                 rep(j, 0, 24)    d.a[j] = nd.a[movp[i][j]];
 83                 dfs(d, step+1, i, 1);
 84             } else if (deep < 2) {
 85                 rep(j, 0, 24)    d.a[j] = nd.a[movp[i][j]];
 86                 dfs(d, step+1, i, deep+1);
 87             }
 88         }
 89     }
 90 }
 91 
 92 void init() {
 93     rep(i, 0, 4) {
 94         nxt[i] = (i+1) % 4;
 95         unxt[i] = (i-1+4)%4;
 96     }
 97     
 98     int i, j, k;
 99     for (k=0,j=0; k<3; ++k,j+=2) {
100         int *mf = movf[k];
101         int *c = movp[j];
102         for (i=0; i<24; ++i)    c[i] = i;
103         for (i=0; i<4; ++i)
104             c[mf[nxt[i]]] = mf[i];
105         for (i=0; i<4; ++i) {
106             c[mf[(nxt[i]<<1)+4]] = mf[(i<<1)+4];
107             c[mf[(nxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
108         }
109         
110         c = movp[j+1];
111         for (i=0; i<24; ++i)    c[i] = i;
112         for (i=0; i<4; ++i)
113             c[mf[unxt[i]]] = mf[i];
114         for (i=0; i<4; ++i) {
115             c[mf[(unxt[i]<<1)+4]] = mf[(i<<1)+4];
116             c[mf[(unxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
117         }
118     }
119     
120     node_t nd;
121     rep(i, 0, 24)    nd.a[i] = i;
122     dfs(nd, 0, -1, 0);
123 }
124 
125 int calc(int *b) {
126     int ret = 0;
127 
128     rep(i, 0, 6) {
129         ++ret;
130         rep(j, 1, 4) {
131             if (b[face[i][j]] != b[face[i][0]]) {
132                 --ret;
133                 break;
134             }
135         }
136     }
137 
138     return ret;
139 }
140 
141 void solve() {
142     ans = 0;
143 
144     rep(i, 0, n+1) {
145         int sz = SZ(vc[i]);
146         rep(j, 0, sz) {
147             rep(k, 0, 24)
148                 b[k] = a[vc[i][j].a[k]];
149             
150             ans = max(ans, calc(b));
151         }
152     }
153 
154     printf("%d\n", ans);
155 }
156 
157 int main() {
158     ios::sync_with_stdio(false);
159     #ifndef ONLINE_JUDGE
160         freopen("data.in", "r", stdin);
161         freopen("data.out", "w", stdout);
162     #endif
163 
164     init();
165     while (scanf("%d", &n)!=EOF) {
166         rep(i, 0, 24)
167             scanf("%d", &a[i]);
168         solve();
169     }
170 
171     #ifndef ONLINE_JUDGE
172         printf("time = %d.\n", (int)clock());
173     #endif
174 
175     return 0;
176 }
View Code


解法七(AC 171ms):
能不能再快点儿?因为有了预处理,我可以将预处理的深搜变为宽搜,这也是碰到深搜实在没什么可剪枝的优化方式。同样,略微有所提高。

  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     char a[24];
 48 } node_t;
 49 
 50 typedef struct {
 51     node_t p;
 52     int pre, deep;
 53 } node;
 54 
 55 int a[24], b[24];
 56 int n;
 57 int face[6][4] = {
 58     {0, 1, 2, 3},
 59     {4, 5, 10, 11},
 60     {6, 7, 12, 13},
 61     {8, 9, 14, 15},
 62     {16, 17, 18, 19},
 63     {20, 21, 22, 23}
 64 };
 65 
 66 int movf[3][12] = {
 67     {0,1,3,2,         22,23,9,8,7,6,5,4},
 68     {4,5,11,10,        0,2,6,12,16,18,20,22},
 69     {6,7,13,12,        2,3,8,14,17,16,11,5}
 70 };
 71 int movp[6][24];
 72 int nxt[4];
 73 int unxt[4];
 74 int ans;
 75 vector<node_t> vc[8];
 76 
 77 void bfs();
 78 
 79 void init() {
 80     rep(i, 0, 4) {
 81         nxt[i] = (i+1) % 4;
 82         unxt[i] = (i-1+4)%4;
 83     }
 84     
 85     int i, j, k;
 86     for (k=0,j=0; k<3; ++k,j+=2) {
 87         int *mf = movf[k];
 88         int *c = movp[j];
 89         for (i=0; i<24; ++i)    c[i] = i;
 90         for (i=0; i<4; ++i)
 91             c[mf[nxt[i]]] = mf[i];
 92         for (i=0; i<4; ++i) {
 93             c[mf[(nxt[i]<<1)+4]] = mf[(i<<1)+4];
 94             c[mf[(nxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 95         }
 96         
 97         c = movp[j+1];
 98         for (i=0; i<24; ++i)    c[i] = i;
 99         for (i=0; i<4; ++i)
100             c[mf[unxt[i]]] = mf[i];
101         for (i=0; i<4; ++i) {
102             c[mf[(unxt[i]<<1)+4]] = mf[(i<<1)+4];
103             c[mf[(unxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
104         }
105     }
106     
107     bfs();
108 }
109 
110 void bfs() {
111     queue<node> Q;
112     node nd, d;
113     int step = 0;
114     
115     rep(i, 0, 24)    nd.p.a[i] = i;
116     nd.pre = -1;
117     nd.deep = 0;
118     Q.push(nd);
119     vc[step].pb(nd.p);
120     
121     while (1) {
122         int sz = SZ(Q);
123         if (sz==0 || ++step>7)
124             break;
125         while (sz--) {
126             nd = Q.front();
127             Q.pop();
128             rep(i, 0, 6) {
129                 if ((i^1) == nd.pre)
130                     continue;
131                 if (i != nd.pre) {
132                     rep(j, 0, 24)    d.p.a[j] = nd.p.a[movp[i][j]];
133                     d.pre = i;
134                     d.deep = 1;
135                     vc[step].pb(d.p);
136                     Q.push(d);
137                     
138                 } else if (nd.deep < 2) {
139                     rep(j, 0, 24)    d.p.a[j] = nd.p.a[movp[i][j]];
140                     d.pre = i;
141                     d.deep = 2;
142                     vc[step].pb(d.p);
143                     Q.push(d);
144                 }
145             }
146         }
147     }
148 }
149 
150 int calc(int *b) {
151     int ret = 0;
152 
153     rep(i, 0, 6) {
154         ++ret;
155         rep(j, 1, 4) {
156             if (b[face[i][j]] != b[face[i][0]]) {
157                 --ret;
158                 break;
159             }
160         }
161     }
162 
163     return ret;
164 }
165 
166 void solve() {
167     ans = 0;
168 
169     rep(i, 0, n+1) {
170         int sz = SZ(vc[i]);
171         rep(j, 0, sz) {
172             rep(k, 0, 24)
173                 b[k] = a[vc[i][j].a[k]];
174             
175             ans = max(ans, calc(b));
176         }
177     }
178 
179     printf("%d\n", ans);
180 }
181 
182 int main() {
183     ios::sync_with_stdio(false);
184     #ifndef ONLINE_JUDGE
185         freopen("data.in", "r", stdin);
186         freopen("data.out", "w", stdout);
187     #endif
188 
189     init();
190     while (scanf("%d", &n)!=EOF) {
191         rep(i, 0, 24)
192             scanf("%d", &a[i]);
193         solve();
194     }
195 
196     #ifndef ONLINE_JUDGE
197         printf("time = %d.\n", (int)clock());
198     #endif
199 
200     return 0;
201 }
View Code


解法八(MLE 109ms):
打表看了一下$[0,7]$共有$98797$种情况,能不能减少?倘若能够减少,也意味着存在着$n_i > n_j$并且进行$n_i$和$n_j$旋转有相同排列的情况,那么$n_i$其实已经不用考虑了。这个排列长度为24,那么怎么判定当前排列是否出现过,并且尽可能节省内存?显然trie树,trie树本来就源自"information retrieval",但是不幸的还是MLE了。

  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     char a[24];
 48 } node_t;
 49 
 50 typedef struct {
 51     node_t p;
 52     int pre, deep;
 53 } node;
 54 
 55 int a[24], b[24];
 56 int n;
 57 int face[6][4] = {
 58     {0, 1, 2, 3},
 59     {4, 5, 10, 11},
 60     {6, 7, 12, 13},
 61     {8, 9, 14, 15},
 62     {16, 17, 18, 19},
 63     {20, 21, 22, 23}
 64 };
 65 
 66 int movf[3][12] = {
 67     {0,1,3,2,         22,23,9,8,7,6,5,4},
 68     {4,5,11,10,        0,2,6,12,16,18,20,22},
 69     {6,7,13,12,        2,3,8,14,17,16,11,5}
 70 };
 71 int movp[6][24];
 72 int nxt[4];
 73 int unxt[4];
 74 int ans;
 75 vector<node_t> vc[8];
 76 
 77 void bfs();
 78 
 79 void init() {
 80     rep(i, 0, 4) {
 81         nxt[i] = (i+1) % 4;
 82         unxt[i] = (i-1+4)%4;
 83     }
 84     
 85     int i, j, k;
 86     for (k=0,j=0; k<3; ++k,j+=2) {
 87         int *mf = movf[k];
 88         int *c = movp[j];
 89         for (i=0; i<24; ++i)    c[i] = i;
 90         for (i=0; i<4; ++i)
 91             c[mf[nxt[i]]] = mf[i];
 92         for (i=0; i<4; ++i) {
 93             c[mf[(nxt[i]<<1)+4]] = mf[(i<<1)+4];
 94             c[mf[(nxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 95         }
 96         
 97         c = movp[j+1];
 98         for (i=0; i<24; ++i)    c[i] = i;
 99         for (i=0; i<4; ++i)
100             c[mf[unxt[i]]] = mf[i];
101         for (i=0; i<4; ++i) {
102             c[mf[(unxt[i]<<1)+4]] = mf[(i<<1)+4];
103             c[mf[(unxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
104         }
105     }
106     
107     bfs();
108 }
109 
110 typedef struct trie_t {
111     static const int maxn = 825145;
112     static const int rt = 1;
113     int nxt[maxn][24];
114     int l;
115     
116     trie_t() {
117         l = 2;
118     }
119     
120     inline int newNode() {
121         assert(l < maxn);
122         return l++;
123     }
124     
125     bool Insert(char *s) {
126         int i = 0;
127         int p = rt;
128         bool ret = false;
129         
130         while (i < 24) {
131             char& id = s[i++];
132             if (!nxt[p][id]) {
133                 nxt[p][id] = newNode();
134                 ret = true;
135             }
136             p = nxt[p][id];
137         }
138         
139         return ret;
140     }
141     
142 } trie_t;
143 
144 trie_t trie;
145 
146 void bfs() {
147     queue<node> Q;
148     node nd, d;
149     int step = 0;
150     
151     rep(i, 0, 24)    nd.p.a[i] = i;
152     nd.pre = -1;
153     nd.deep = 0;
154     Q.push(nd);
155     trie.Insert(nd.p.a);
156     vc[step].pb(nd.p);
157     
158     while (1) {
159         int sz = SZ(Q);
160         if (sz==0 || ++step>7)
161             break;
162         while (sz--) {
163             nd = Q.front();
164             Q.pop();
165             rep(i, 0, 6) {
166                 if ((i^1) == nd.pre)
167                     continue;
168                 if (i != nd.pre) {
169                     rep(j, 0, 24)    d.p.a[j] = nd.p.a[movp[i][j]];
170                     d.pre = i;
171                     d.deep = 1;
172                     
173                 } else if (nd.deep < 2) {
174                     rep(j, 0, 24)    d.p.a[j] = nd.p.a[movp[i][j]];
175                     d.pre = i;
176                     d.deep = 2;
177                 } else {
178                     continue;
179                 }
180                 
181                 if (trie.Insert(d.p.a)) {
182                     vc[step].pb(d.p);
183                     Q.push(d);
184                 }
185             }
186         }
187     }
188     
189     #ifndef ONLINE_JUDGE
190     rep(i, 0, 8)
191         printf("%d\n", SZ(vc[i]));
192     printf("l = %d\n", trie.l);
193     #endif
194 }
195 
196 int calc(int *b) {
197     int ret = 0;
198 
199     rep(i, 0, 6) {
200         ++ret;
201         rep(j, 1, 4) {
202             if (b[face[i][j]] != b[face[i][0]]) {
203                 --ret;
204                 break;
205             }
206         }
207     }
208 
209     return ret;
210 }
211 
212 void solve() {
213     ans = 0;
214 
215     rep(i, 0, n+1) {
216         int sz = SZ(vc[i]);
217         rep(j, 0, sz) {
218             rep(k, 0, 24)
219                 b[k] = a[vc[i][j].a[k]];
220             
221             ans = max(ans, calc(b));
222         }
223     }
224 
225     printf("%d\n", ans);
226 }
227 
228 int main() {
229     ios::sync_with_stdio(false);
230     #ifndef ONLINE_JUDGE
231         freopen("data.in", "r", stdin);
232         freopen("data.out", "w", stdout);
233     #endif
234 
235     init();
236     while (scanf("%d", &n)!=EOF) {
237         rep(i, 0, 24)
238             scanf("%d", &a[i]);
239         solve();
240     }
241 
242     #ifndef ONLINE_JUDGE
243         printf("time = %d.\n", (int)clock());
244     #endif
245 
246     return 0;
247 }
View Code

 
解法九(AC G++93ms C++109ms):
还是上一个思路,能不能使用别的数据结构代替trie树?可以将长为24的排列想象成字符串,因此适用于字符串的算法都可以采用,所以果断试试哈希(可以与trie对拍一下所有排列)。LCP哈希可以过,ELFHash等都试了一下,过不了。这样,就将$98797$近乎减少了一半,最终仅$44971$种情况,时间上也提高了很多。

  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 #define ULL unsigned __int64
 46 
 47 typedef struct {
 48     char a[24];
 49 } node_t;
 50 
 51 typedef struct {
 52     node_t p;
 53     int pre, deep;
 54 } node;
 55 
 56 int a[24], b[24];
 57 int n;
 58 int face[6][4] = {
 59     {0, 1, 2, 3},
 60     {4, 5, 10, 11},
 61     {6, 7, 12, 13},
 62     {8, 9, 14, 15},
 63     {16, 17, 18, 19},
 64     {20, 21, 22, 23}
 65 };
 66 
 67 int movf[3][12] = {
 68     {0,1,3,2,         22,23,9,8,7,6,5,4},
 69     {4,5,11,10,        0,2,6,12,16,18,20,22},
 70     {6,7,13,12,        2,3,8,14,17,16,11,5}
 71 };
 72 int movp[6][24];
 73 int nxt[4];
 74 int unxt[4];
 75 int ans;
 76 vector<node_t> vc[8];
 77 
 78 void bfs();
 79 
 80 void init() {
 81     rep(i, 0, 4) {
 82         nxt[i] = (i+1) % 4;
 83         unxt[i] = (i-1+4)%4;
 84     }
 85     
 86     int i, j, k;
 87     for (k=0,j=0; k<3; ++k,j+=2) {
 88         int *mf = movf[k];
 89         int *c = movp[j];
 90         for (i=0; i<24; ++i)    c[i] = i;
 91         for (i=0; i<4; ++i)
 92             c[mf[nxt[i]]] = mf[i];
 93         for (i=0; i<4; ++i) {
 94             c[mf[(nxt[i]<<1)+4]] = mf[(i<<1)+4];
 95             c[mf[(nxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
 96         }
 97         
 98         c = movp[j+1];
 99         for (i=0; i<24; ++i)    c[i] = i;
100         for (i=0; i<4; ++i)
101             c[mf[unxt[i]]] = mf[i];
102         for (i=0; i<4; ++i) {
103             c[mf[(unxt[i]<<1)+4]] = mf[(i<<1)+4];
104             c[mf[(unxt[i]<<1|1)+4]] = mf[(i<<1|1)+4];
105         }
106     }
107     
108     bfs();
109 }
110 
111 typedef struct Hash {
112     static const int MOD = 754283;
113     set<ULL> st;
114     
115     void clear() {
116         st.clr();
117     }
118     
119     ULL HashCode(const char *s) {
120         ULL ret = 0;
121         
122         rep(i, 0, 24)
123             ret = ret * MOD + s[i];
124             
125         return ret;
126     }
127     
128     bool find(const node_t& p) {
129         ULL h = HashCode(p.a);
130         if (st.find(h) == st.end()) {
131             st.insert(h);
132             return false;
133         } else {
134             return true;
135         }
136     }
137     
138 } Hash;
139 
140 Hash tb;
141 
142 void bfs() {
143     queue<node> Q;
144     node nd, d;
145     int step = 0;
146     
147     rep(i, 0, 24)    nd.p.a[i] = i;
148     nd.pre = -1;
149     nd.deep = 0;
150     Q.push(nd);
151     
152     tb.clr();
153     tb.find(nd.p);
154     vc[step].pb(nd.p);
155     
156     while (1) {
157         int sz = SZ(Q);
158         if (sz==0 || ++step>7)
159             break;
160         while (sz--) {
161             nd = Q.front();
162             Q.pop();
163             rep(i, 0, 6) {
164                 if ((i^1) == nd.pre)
165                     continue;
166                 if (i != nd.pre) {
167                     rep(j, 0, 24)    d.p.a[j] = nd.p.a[movp[i][j]];
168                     d.pre = i;
169                     d.deep = 1;
170                     
171                 } else if (nd.deep < 2) {
172                     rep(j, 0, 24)    d.p.a[j] = nd.p.a[movp[i][j]];
173                     d.pre = i;
174                     d.deep = 2;
175                 } else {
176                     continue;
177                 }
178                 
179                 if (!tb.find(d.p)) {
180                     vc[step].pb(d.p);
181                     Q.push(d);
182                 }
183             }
184         }
185     }
186 }
187 
188 int calc(int *b) {
189     int ret = 0;
190 
191     rep(i, 0, 6) {
192         ++ret;
193         rep(j, 1, 4) {
194             if (b[face[i][j]] != b[face[i][0]]) {
195                 --ret;
196                 break;
197             }
198         }
199     }
200 
201     return ret;
202 }
203 
204 void solve() {
205     ans = 0;
206 
207     rep(i, 0, n+1) {
208         int sz = SZ(vc[i]);
209         rep(j, 0, sz) {
210             rep(k, 0, 24)
211                 b[k] = a[vc[i][j].a[k]];
212             
213             ans = max(ans, calc(b));
214         }
215     }
216 
217     printf("%d\n", ans);
218 }
219 
220 int main() {
221     ios::sync_with_stdio(false);
222     #ifndef ONLINE_JUDGE
223         freopen("data.in", "r", stdin);
224         freopen("data.out", "w", stdout);
225     #endif
226 
227     init();
228     while (scanf("%d", &n)!=EOF) {
229         rep(i, 0, 24)
230             scanf("%d", &a[i]);
231         solve();
232     }
233 
234     #ifndef ONLINE_JUDGE
235         printf("time = %d.\n", (int)clock());
236     #endif
237 
238     return 0;
239 }
View Code


93ms就是目前最快的了,因为耗内存,故排第4。后面又尝试了一下写了个内存池代替vector,但是效果并不明显。

这个题目是13年regional的题目,虽然不是特别难,但是可以看到结合多种算法不断进行优化这个过程很重要。
最开始学习算法的时候,基本上没什么思路,很多dp、二分都不会写。碰到TLE基本就要看题解了,现在逐渐可以自己想思路,找优化方式,我觉得这是一个显著的进步,这也是一种提高的方式。我认为算法的学习没什么捷径,深入了解算法的基本思路和证明过程,以及如何对基本算法进行提升很重要。

你可能感兴趣的:(【HDOJ】4801 Pocket Cube 的几种解法和优化)