zoukankan      html  css  js  c++  java
  • HDU 2953 Rubiks Cube

    二阶魔方旋转,数据比较大,而且六面均可旋转(与HDU3459不同),结束状态不确定(与HDU2691不同),status里面各种WA,TLE,MLE,只有一人AC,果断膜拜,然后标记为神题就没去看了,后来看了那人代码,方法比较巧妙,但也并不是什么高深难懂的算法,可以说是双广+预处理

    对每个面标号一下,我们用数字表示小面,字母表示颜色,用[字母]表示大面,如下

    00 01
    02 03
    04 05 06 07 08 09 10 11
    12 13 14 15 16 17 18 19
    20 21
    22 23

    OO
    OO
    RR GG BB WW
    RR GG BB WW
    YY
    YY

    [O]
    [R][G][B][W]
    [Y]
      
    首先我们可以想到,一个面的顺时针旋转相当于他的相对面逆时针旋转,这样我们可以将六个面的旋转转化为三个面的旋转,比如说我们对于[R]面的顺时针旋转就相当于对[B]面的逆时针旋转,而且这样步数是不会增大的,而状态减少了许多。
     

    然后我们去找魔方的特殊性,二阶魔方的24个面并不是独立的,从魔方结构就能看出一个二阶魔方是分为8个小块的,每个块三种颜色,比如说图中的(3,5,6)是在同一块上,(1,7,8)是在同一块上,这样我们根据他的特殊性从每一个块去分析

     
    我们只做[R][G][O]面的正逆旋转,这样的话(17,18,22)这一块的是不会移动的,即[B][W][Y]这三个面的最终颜色是确定的,然后再去扩展,与B和W在同一块里的除了Y之外还有O,B和Y还有G,Y和W还有R。按照上面所说的:我们将要求的魔方中的17 18 22三面分别变为B W Y,然后根据每块的相连关系将另外三面都重新染色,这样我们就将每一个魔方都转化为最终状态都相同情况了
      
    然后的做法就很简单了,我们可以从一个状态开始扩展做预处理,但是保存全部状态内存消耗太大,我们可以只预处理出7层情况(二阶魔方最多需要14步到达最终状态),然后对每一个魔方,将它进行重新染色后进行广搜,搜到一个已经预处理过的状态时就返回答案,答案为两边步数之和,这样这题就搞定了~~


      1 #include<cstdio>
    2 #include<cstring>
    3 #include<map>
    4 #include<queue>
    5 #include<cstdlib>
    6 using namespace std;
    7
    8 int cvr[6][12]={
    9 {4,12,13,5,3,2,11,19,20,21,14,6},
    10 {12,13,5,4,11,19,20,21,14,6,3,2},
    11 {7,6,14,15,1,3,5,13,21,23,16,8},
    12 {6,14,15,7,5,13,21,23,16,8,1,3},
    13 {1,0,2,3,8,9,10,11,4,5,6,7},
    14 {0,2,3,1,10,11,4,5,6,7,8,9}};
    15
    16 int block[8][3]={
    17 {3,5,6},{1,7,8},{0,9,10},{2,4,11},
    18 {12,19,20},{13,14,21},{15,16,23},{17,18,22}};
    19
    20 struct S{
    21 char s[30];
    22
    23 friend bool operator< (const S& a,const S& b){
    24 return strcmp(a.s,b.s)<0;
    25 }
    26
    27 void change(){
    28 map<char,char> col;
    29 map<char,bool> flag;
    30 col[s[17]]='B'; flag[s[17]]=true;
    31 col[s[18]]='W'; flag[s[18]]=true;
    32 col[s[22]]='Y'; flag[s[22]]=true;
    33 for(int i=0;i<7;i++){
    34 int cnt=0,sum=0,has=3;
    35 if(flag[s[block[i][0]]]){cnt++;sum+=col[s[block[i][0]]];has-=0;}
    36 if(flag[s[block[i][1]]]){cnt++;sum+=col[s[block[i][1]]];has-=1;}
    37 if(flag[s[block[i][2]]]){cnt++;sum+=col[s[block[i][2]]];has-=2;}
    38 if(cnt!=2) continue;
    39 if(sum=='B'+'W') col[s[block[i][has]]]='O';
    40 if(sum=='B'+'Y') col[s[block[i][has]]]='G';
    41 if(sum=='Y'+'W') col[s[block[i][has]]]='R';
    42 }
    43 for(int i=0;i<24;i++){
    44 s[i]=col[s[i]];
    45 }
    46 }
    47 }s;
    48 map<S,int> step;
    49
    50 void in(char &c){
    51 c=getchar();
    52 while(c<=32) c=getchar();
    53 }
    54
    55 void bfs0(){
    56 strcpy(s.s,"OOOORRGGBBWWRRGGBBWWYYYY");
    57 step.clear();
    58 step[s]=-1;
    59
    60 queue<pair<S,int> > que;
    61 que.push(make_pair(s,0));
    62 while(!que.empty()){
    63 S u=que.front().first;
    64 int d=que.front().second;
    65 que.pop();
    66 for(int i=0;i<6;i++){
    67 S v=u;
    68 for(int j=0;j<12;j++){
    69 v.s[cvr[i][j]]=u.s[cvr[i^1][j]];
    70 }
    71 if(step[v]) continue;
    72 step[v]=d+1;
    73 if(d<6){
    74 que.push(make_pair(v,d+1));
    75 }
    76 }
    77 }
    78 }
    79
    80 map<S,bool> vis;
    81 int bfs1(){
    82 s.change();
    83
    84 if(step[s]){
    85 if(step[s]==-1) return 0;
    86 else return step[s];
    87 }
    88 vis.clear();
    89 vis[s]=true;
    90
    91 queue<pair<S,int> > que;
    92 que.push(make_pair(s,0));
    93 while(!que.empty()){
    94 S u=que.front().first;
    95 int d=que.front().second;
    96 que.pop();
    97 for(int i=0;i<6;i++){
    98 S v=u;
    99 for(int j=0;j<12;j++){
    100 v.s[cvr[i][j]]=u.s[cvr[i^1][j]];
    101 }
    102 if(vis[v]) continue;
    103 vis[v]=true;
    104 if(step[v]){
    105 if(step[v]==-1) return d+1;
    106 else return step[v]+d+1;
    107 }
    108 que.push(make_pair(v,d+1));
    109 }
    110 }
    111 return -1;
    112 }
    113
    114 int main(){
    115 bfs0();
    116
    117 int t;
    118 scanf("%d",&t);
    119 while(t--){
    120 for(int i=0;i<24;i++){
    121 in(s.s[i]);
    122 }
    123
    124 int ans=bfs1();
    125 printf("%d\n",ans);
    126 }
    127 }

      

  • 相关阅读:
    Git理解
    Java基础之四、字符和字符串 异常处理
    魔方第三层复原技巧
    Java基础之三、类的特性和接口
    Java基础之二、类的知识
    Java基础之一、入门知识
    UML之三、建模元素(2)
    看懂棒球-规则、数据
    【转载】自助终端设备安全剖析 (深度好文)
    CVE-2017-12615 Tomcat远程代码执行
  • 原文地址:https://www.cnblogs.com/ambition/p/Rubiks_Cube.html
Copyright © 2011-2022 走看看