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基本就要看题解了,现在逐渐可以自己想思路,找优化方式,我觉得这是一个显著的进步,这也是一种提高的方式。我认为算法的学习没什么捷径,深入了解算法的基本思路和证明过程,以及如何对基本算法进行提升很重要。

  • 相关阅读:
    delphi7在windows server 2003企业版上不能打开项目的选项(Options)窗口的解决方法
    简单的两个字“谢谢”,会让我坚持我的写作,我也要谢谢你们
    F41GUT 安装Windows server 2003系统后无法安装显卡驱动的解决办法
    远程桌面无法登录windows server 2003服务器
    F41GUT 安装Windows server 2003系统后无法安装显卡驱动的解决办法
    MS SQL Server 2000版在windows server 2003企业版系统上运行时造成数据库suspect的解决方法
    delphi7在windows server 2003企业版上不能打开项目的选项(Options)窗口的解决方法
    远程桌面无法登录windows server 2003服务器
    MS SQL Server 2000版在windows server 2003企业版系统上运行时造成数据库suspect的解决方法
    关于ajax 和josn
  • 原文地址:https://www.cnblogs.com/bombe1013/p/5285901.html
Copyright © 2011-2022 走看看