[C++] C++实现超赞的解魔方的机器人代码 →→→→→进入此内容的聊天室

来自 , 2020-03-25, 写在 C++, 查看 136 次.
URL http://www.code666.cn/view/35bf9850
  1. /**********************************************************************
  2.  *
  3.  * A cube 'state' is a vector<int> with 40 entries, the first 20
  4.  * are a permutation of {0,...,19} and describe which cubie is at
  5.  * a certain position (regarding the input ordering). The first
  6.  * twelve are for edges, the last eight for corners.
  7.  *
  8.  * The last 20 entries are for the orientations, each describing
  9.  * how often the cubie at a certain position has been turned
  10.  * counterclockwise away from the correct orientation. Again the
  11.  * first twelve are edges, the last eight are corners. The values
  12.  * are 0 or 1 for edges and 0, 1 or 2 for corners.
  13.  *
  14.  * http://www.sharejs.com
  15.  **********************************************************************/
  16.  
  17. #include <iostream>
  18. #include <string>
  19. #include <vector>
  20. #include <map>
  21. #include <queue>
  22. #include <algorithm>
  23. using namespace std;
  24.  
  25. //----------------------------------------------------------------------
  26.  
  27. typedef vector<int> vi;
  28.  
  29. //----------------------------------------------------------------------
  30.  
  31. int applicableMoves[] = { 0, 262143, 259263, 74943, 74898 };
  32.  
  33. // TODO: Encode as strings, e.g. for U use "ABCDABCD"
  34.  
  35. int affectedCubies[][8] = {
  36.   {  0,  1,  2,  3,  0,  1,  2,  3 },   // U
  37.   {  4,  7,  6,  5,  4,  5,  6,  7 },   // D
  38.   {  0,  9,  4,  8,  0,  3,  5,  4 },   // F
  39.   {  2, 10,  6, 11,  2,  1,  7,  6 },   // B
  40.   {  3, 11,  7,  9,  3,  2,  6,  5 },   // L
  41.   {  1,  8,  5, 10,  1,  0,  4,  7 },   // R
  42. };
  43.  
  44. vi applyMove ( int move, vi state ) {
  45.   int turns = move % 3 + 1;
  46.   int face = move / 3;
  47.   while( turns-- ){
  48.     vi oldState = state;
  49.     for( int i=0; i<8; i++ ){
  50.       int isCorner = i > 3;
  51.       int target = affectedCubies[face][i] + isCorner*12;
  52.       int killer = affectedCubies[face][(i&3)==3 ? i-3 : i+1] + isCorner*12;;
  53.       int orientationDelta = (i<4) ? (face>1 && face<4) : (face<2) ? 0 : 2 - (i&1);
  54.       state[target] = oldState[killer];
  55.       //state[target+20] = (oldState[killer+20] + orientationDelta) % (2 + isCorner);
  56.       state[target+20] = oldState[killer+20] + orientationDelta;
  57.       if( !turns )
  58.     state[target+20] %= 2 + isCorner;
  59.     }
  60.   }
  61.   return state;
  62. }
  63.  
  64. int inverse ( int move ) {
  65.   return move + 2 - 2 * (move % 3);
  66. }
  67.  
  68. //----------------------------------------------------------------------
  69.  
  70. int phase;
  71.  
  72. //----------------------------------------------------------------------
  73.  
  74. vi id ( vi state ) {
  75.  
  76.   //--- Phase 1: Edge orientations.
  77.   if( phase < 2 )
  78.     return vi( state.begin() + 20, state.begin() + 32 );
  79.  
  80.   //-- Phase 2: Corner orientations, E slice edges.
  81.   if( phase < 3 ){
  82.     vi result( state.begin() + 31, state.begin() + 40 );
  83.     for( int e=0; e<12; e++ )
  84.       result[0] |= (state[e] / 8) << e;
  85.     return result;
  86.   }
  87.  
  88.   //--- Phase 3: Edge slices M and S, corner tetrads, overall parity.
  89.   if( phase < 4 ){
  90.     vi result( 3 );
  91.     for( int e=0; e<12; e++ )
  92.       result[0] |= ((state[e] > 7) ? 2 : (state[e] & 1)) << (2*e);
  93.     for( int c=0; c<8; c++ )
  94.       result[1] |= ((state[c+12]-12) & 5) << (3*c);
  95.     for( int i=12; i<20; i++ )
  96.       for( int j=i+1; j<20; j++ )
  97.         result[2] ^= state[i] > state[j];
  98.     return result;
  99.   }
  100.  
  101.   //--- Phase 4: The rest.
  102.   return state;
  103. }
  104.  
  105. //----------------------------------------------------------------------
  106.  
  107. int main ( int argc, char** argv ) {
  108.  
  109.   //--- Define the goal.
  110.   string goal[] = { "UF", "UR", "UB", "UL", "DF", "DR", "DB", "DL", "FR", "FL", "BR", "BL",
  111.                     "UFR", "URB", "UBL", "ULF", "DRF", "DFL", "DLB", "DBR" };
  112.  
  113.   //--- Prepare current (start) and goal state.
  114.   vi currentState( 40 ), goalState( 40 );
  115.   for( int i=0; i<20; i++ ){
  116.    
  117.     //--- Goal state.
  118.     goalState[i] = i;
  119.    
  120.     //--- Current (start) state.
  121.     string cubie = argv[i+1];
  122.     while( (currentState[i] = find( goal, goal+20, cubie ) - goal) == 20){
  123.       cubie = cubie.substr( 1 ) + cubie[0];
  124.       currentState[i+20]++;
  125.     }
  126.   }
  127.  
  128.   //--- Dance the funky Thistlethwaite...
  129.   while( ++phase < 5 ){
  130.    
  131.     //--- Compute ids for current and goal state, skip phase if equal.
  132.     vi currentId = id( currentState ), goalId = id( goalState );
  133.     if( currentId == goalId )
  134.       continue;
  135.    
  136.     //--- Initialize the BFS queue.
  137.     queue<vi> q;
  138.     q.push( currentState );
  139.     q.push( goalState );
  140.    
  141.     //--- Initialize the BFS tables.
  142.     map<vi,vi> predecessor;
  143.     map<vi,int> direction, lastMove;
  144.     direction[ currentId ] = 1;
  145.     direction[ goalId ] = 2;
  146.    
  147.     //--- Dance the funky bidirectional BFS...
  148.     while( 1 ){
  149.      
  150.       //--- Get state from queue, compute its ID and get its direction.
  151.       vi oldState = q.front();
  152.       q.pop();
  153.       vi oldId = id( oldState );
  154.       int& oldDir = direction[oldId];
  155.      
  156.       //--- Apply all applicable moves to it and handle the new state.
  157.       for( int move=0; move<18; move++ ){
  158.         if( applicableMoves[phase] & (1 << move) ){
  159.          
  160.           //--- Apply the move.
  161.           vi newState = applyMove( move, oldState );
  162.           vi newId = id( newState );
  163.           int& newDir = direction[newId];
  164.          
  165.           //--- Have we seen this state (id) from the other direction already?
  166.           //--- I.e. have we found a connection?
  167.           if( newDir  &&  newDir != oldDir ){
  168.            
  169.             //--- Make oldId represent the forwards and newId the backwards search state.
  170.             if( oldDir > 1 ){
  171.               swap( newId, oldId );
  172.               move = inverse( move );
  173.             }
  174.            
  175.             //--- Reconstruct the connecting algorithm.
  176.             vi algorithm( 1, move );
  177.             while( oldId != currentId ){
  178.               algorithm.insert( algorithm.begin(), lastMove[ oldId ] );
  179.               oldId = predecessor[ oldId ];
  180.             }
  181.             while( newId != goalId ){
  182.               algorithm.push_back( inverse( lastMove[ newId ] ));
  183.               newId = predecessor[ newId ];
  184.             }
  185.            
  186.             //--- Print and apply the algorithm.
  187.             for( int i=0; i<(int)algorithm.size(); i++ ){
  188.               cout << "UDFBLR"[algorithm[i]/3] << algorithm[i]%3+1;
  189.               currentState = applyMove( algorithm[i], currentState );
  190.             }
  191.            
  192.             //--- Jump to the next phase.
  193.             goto nextPhasePlease;
  194.           }
  195.          
  196.           //--- If we've never seen this state (id) before, visit it.
  197.           if( ! newDir ){
  198.             q.push( newState );
  199.             newDir = oldDir;
  200.             lastMove[ newId ] = move;
  201.             predecessor[ newId ] = oldId;
  202.           }
  203.         }
  204.       }
  205.     }
  206.   nextPhasePlease:
  207.     ;
  208.   }
  209. }
  210. //cpp/8890

回复 "C++实现超赞的解魔方的机器人代码"

这儿你可以回复上面这条便签

captcha