ZOJ 2477Magic Cube(打表模拟)

感觉这道题真的是很好的一道题,我比较认可这个方法就是按照读入顺序来对颜色块,进行编码然后预先打表处理出每个面顺逆时针旋转之后的位置,认真一点把表打对,然后可以利用迭代加深搜索出最小的步数。

#include <bits/stdc++.h>
using namespace std;

char readchar() {
    char ch = 0;
    while (!isalpha(ch)) {
        ch = getchar();
    }
    return ch;
}

char cube[54];
const int cell[6][9] = { //每行第一个都是块的中心 以读入的顺序来对每个颜色进行编号
        {4, 0, 1, 2, 3, 5, 6, 7, 8},
        {22, 9, 10, 11, 21, 23, 33, 34, 35},
        {25, 12, 13, 14, 24, 26, 36, 37, 38},
        {28, 15, 16, 17, 27, 29, 39, 40, 41},
        {31, 18, 19, 20, 30, 32, 42, 43, 44},
        {49, 45, 46, 47, 48, 50, 51, 52, 53}
};

const int change[12][20] = {  //一共12行分别表示0~5面的顺逆时针旋转,每次只旋转20个,因为中心快永远都不会动
        {11, 23, 35, 34, 33, 21, 9, 10, 51, 48, 45, 36, 24, 12, 6, 3, 0, 20, 32, 44},
        {9, 10, 11, 23, 35, 34, 33, 21, 36, 24, 12, 6, 3, 0, 20, 32, 44, 51, 48, 45},
        {14, 13, 26, 38, 37, 36, 24, 12, 45, 46, 47, 39, 27, 15, 8, 7, 6, 11, 23, 35},
        {12, 24, 13, 14, 26, 38, 37, 36, 39, 27, 15, 8, 7, 6, 11, 23, 35, 45, 46, 47},
        {17, 29, 41, 40, 39, 27, 15, 16, 47, 50, 53, 42, 30, 18, 2, 5, 8, 14, 26, 38},
        {15, 16, 17, 29, 41, 40, 39, 27, 42, 30, 18, 2, 5, 8, 14, 26, 38, 47, 50, 53},
        {18, 19, 20, 32, 44, 43, 42, 30, 53, 52, 51, 33, 21, 9, 0, 1, 2, 17, 29, 41},
        {42, 30, 18, 19, 20, 32, 44, 43, 33, 21, 9, 0, 1, 2, 17, 29, 41, 53, 52, 51},
        {0, 1, 2, 5, 8, 7, 6, 3, 12, 13, 14, 15, 16, 17, 18, 19, 20, 9, 10, 11},
        {6, 3, 0, 1, 2, 5, 8, 7, 15, 16, 17, 18, 19, 20, 9, 10, 11, 12, 13, 14},
        {45, 46, 47, 50, 53, 52, 51, 48, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33},
        {51, 48, 45, 46, 47, 50, 53, 52, 41, 40, 39, 38, 37, 36, 35, 34, 33, 44, 43, 42}
};

bool ok() {
    for (int i = 0; i < 6; ++i) {
        for (int j = 1; j < 9; ++j) {
            if (cube[cell[i][0]] != cube[cell[i][j]])
                return false;
        }
    }
    return true;
}

void rotate(int layer) {
    char prv[54];
    copy(cube, cube + 54, prv);
    for (int i = 0; i < 20; ++i) {
        prv[change[layer][i]] = cube[change[layer ^ 1][i]];
    }//利用异或颠倒奇偶性的性质
    copy(prv, prv + 54, cube);
}

int ans[10];
bool dfs(int d, int limit) {  //dfs
    if (d > limit) return false;
    if (ok()) return true;
    for (int i = 0; i < 12; ++i) {
        ans[d] = i;
        rotate(i); //转一下
        if (dfs(d + 1, limit)) return true;
        rotate(i ^ 1); //再转回来
    }
    return false;
}

int main() {
    int t; scanf("%d", &t);
    while (t--) {
        for (int i = 0; i < 54; ++i) cube[i] = readchar();
        for (int i = 0; ; ++i) { // 迭代加深
            if (6 == i) {
                printf("-1\n");
                break;
            }
            if (dfs(0, i)) {
                if (0 == i)
                    printf("0\n");
                else {
                    printf("%d\n", i);
                    for (int j = 0; j < i; ++j) {

                        printf("%d %d\n", ans[j] / 2, ((ans[j] & 1) ? -1 : 1));
                    }
                }
                break;
            }
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值