zoukankan      html  css  js  c++  java
  • 【HDOJ】4801 Pocket Cube 的几种解法和优化

    1. 题目描述
    给定一个$2 imes 2 imes 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('
    ');
    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('
    ');
    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
    ", 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.
    ", (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
    ", 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.
    ", (int)clock());
    190     #endif
    191 
    192     return 0;
    193 }
    View Code

    果断TLE了。分析为什么?最坏情况下深搜的深度为7,每次深搜有12种旋转方式($6 ext{ faces } imes 2 ext{ 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
    ", 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.
    ", (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
    ", 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.
    ", (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
    ", 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.
    ", (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
    ", 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.
    ", (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
    ", 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.
    ", (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
    ", SZ(vc[i]));
    192     printf("l = %d
    ", 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
    ", 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.
    ", (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
    ", 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.
    ", (int)clock());
    236     #endif
    237 
    238     return 0;
    239 }
    View Code


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

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

  • 相关阅读:
    【STM32F429】第6章 ThreadX操作系统移植(IAR)
    【STM32F429】第5章 ThreadX操作系统移植(MDK AC6)
    【硬核】超强八位半开源万用表
    【STM32H7】第4章 ThreadX操作系统移植(MDK AC5)
    【STM32F429】第4章 ThreadX操作系统移植(MDK AC5)
    【STM32H7】第3章 ThreadX操作系统介绍
    【STM32F429】第3章 ThreadX操作系统介绍
    ST发布M33内核新品STM32U5,首款40nm工艺超低功耗系列,160MHz全速运行19uA/MHz
    CAN总线35周年特别篇 -- CAN总线的前世今生
    【STM32H7】第2章 初学ThreadX准备工作
  • 原文地址:https://www.cnblogs.com/bombe1013/p/5285901.html
Copyright © 2011-2022 走看看