最大深度只有5层, 所以用IDA* 算法
每块魔方的中间位置的颜色是不会变的,因此可以用总共不在原来面上的方块数来作为h函数
模拟每一个旋转变换有些难看,拿笔自己写一写就知道了
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int n, m;
int depth;
int ans[ 10 ], dir[ 10 ];
char a[ 100 ];
//所有的数字都代表位置
int centre[ 6 ] = {5, 23, 26, 29, 32, 50};
int row[ 6 ][ 10 ] = {{1, 2, 3, 4, 5, 6, 7, 8, 9}, {10, 11, 12, 22, 23, 24, 34, 35, 36},
{13, 14, 15, 25, 26, 27, 37, 38, 39}, {16, 17, 18, 28, 29, 30, 40, 41, 42},
{19, 20, 21, 31, 32, 33, 43, 44, 45}, {46, 47, 48, 49, 50, 51, 52, 53, 54}};
/*
给每个位置标号
1 2 3
4 5 6
7 8 9
10 11 12 13 14 15 16 17 18 19 20 21
22 23 24 25 26 27 28 29 30 31 32 33
34 35 36 37 38 39 40 41 42 43 44 45
46 47 48
49 50 51
52 53 54
*/
/*
* 单独第0个面
* 1 4 7
* ----------
* 21 | 10 11 12 | 13
* 33 | 22 23 24 | 25
* 45 | 34 35 36 | 37
* ----------
52 49 46
*/
// 6个面,每个面顺逆时针
//每两行一组,如change[0] --> change[1] 就是 12 移到 10,逆时针
int change[ 12 ][ 20 ] = {
{12, 24, 36, 35, 34, 22, 10, 11, 13, 25, 37, 46, 49, 52, 45, 33, 21, 1, 4, 7},
{10, 11, 12, 24, 36, 35, 34, 22, 1, 4, 7, 13, 25, 37, 46, 49, 52, 45, 33, 21},
{15, 27, 39, 38, 37, 25, 13, 14, 16, 28, 40, 48, 47, 46, 36, 24, 12, 7, 8, 9},
{13, 14, 15, 27, 39, 38, 37, 25, 7, 8, 9, 16, 28, 40, 48, 47, 46, 36, 24, 12},
{18, 30, 42, 41, 40, 28, 16, 17, 19, 31, 43, 54, 51, 48, 39, 27, 15, 9, 6, 3},
{16, 17, 18, 30, 42, 41, 40, 28, 9, 6, 3, 19, 31, 43, 54, 51, 48, 39, 27, 15},
{21, 33, 45, 44, 43, 31, 19, 20, 3, 2, 1, 10, 22, 34, 52, 53, 54, 42, 30, 18},
{19, 20, 21, 33, 45, 44, 43, 31, 42, 30, 18, 3, 2, 1, 10, 22, 34, 52, 53, 54},
{3, 6, 9, 8, 7, 4, 1, 2, 18, 17, 16, 15, 14, 13, 12, 11, 10, 21, 20, 19},
{1, 2, 3, 6, 9, 8, 7, 4, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10},
{48, 51, 54, 53, 52, 49, 46, 47, 40, 41, 42, 43, 44, 45, 34, 35, 36, 37, 38, 39},
{46, 47, 48, 51, 54, 53, 52, 49, 37, 38, 39, 40, 41, 42, 43, 44, 45, 34, 35, 36}};
//所有面的中心不变,比较每个面周围八个和中心有多少个不一样的,作为距离
int geth () {
int sum = 0;
for ( int i = 0; i < 6; ++i )
for ( int j = 0; j < 9; ++j )
if ( a[ row[ i ][ j ] ] != a[ centre[ i ] ] )
++sum;
return sum;
}
bool ID_Astar ( int d ) {
int h = geth ();
if ( d + ceil ( h / 12.0 ) > depth )
return false;
if ( h == 0 && d == depth )
return true;
char maze[ 100 ];
//搜索12种操作
for ( int i = 0; i < 12; ++i ) {
memcpy ( maze, a, sizeof ( a ) );
for ( int j = 0; j < 20; ++j )
a[ change[ i ][ j ] ] = maze[ change[ i ^ 1 ][ j ] ];
//记录方向
ans[ d ] = i / 2;
if ( !( i & 1 ) )
dir[ d ] = 1;
else
dir[ d ] = -1;
if ( ID_Astar ( d + 1 ) )
return true;
memcpy ( a, maze, sizeof ( maze ) );
}
return false;
}
int main () {
int T;
scanf ( "%d", &T );
while ( T-- ) {
for ( int i = 1; i <= 54; ++i )
cin >> a[ i ];
if ( !geth () ) {
printf ( "0\n" );
continue;
}
//固定深度
for ( depth = 1; depth <= 5; depth++ ) {
if ( ID_Astar ( 0 ) )
break;
}
if ( depth == 6 )
printf ( "-1\n" );
else {
printf ( "%d\n", depth );
for ( int i = 0; i < depth; ++i )
printf ( "%d %d\n", ans[ i ], dir[ i ] );
}
}
return 0;
}