征战蓝桥 —— 2017年第八届 —— C/C++A组第3题——魔方状态

题目

二阶魔方就是只有2层的魔方,只由8个小块组成。
如图p1.png所示。
在这里插入图片描述
小明很淘气,他只喜欢3种颜色,所以把家里的二阶魔方重新涂了颜色,如下:

前面:橙色
右面:绿色
上面:黄色
左面:绿色
下面:橙色
后面:黄色

请你计算一下,这样的魔方被打乱后,一共有多少种不同的状态。

如果两个状态经过魔方的整体旋转后,各个面的颜色都一致,则认为是同一状态。

请提交表示状态数的整数,不要填写任何多余内容或说明文字。

代码

#include <vector>
#include <set>
#include <iostream>

using namespace std;
typedef char st[8][7];
st start = {{"oybbgb"},
            {"oygbbb"},
            {"bygbby"},
            {"bybbgy"},
            {"obbogb"},
            {"obgobb"},
            {"bbgoby"},
            {"bbbogy"}};
st q[4000000];
set<string> all_state;
int ans, front, tail;


string to_string(st &a) {
    string ans;
    for (int i = 0; i < 8; ++i) {
        ans += a[i];
    }
    return ans;
}

//上层的块的旋转,面的相对位置调换
void ucell(char *a) {
    swap(a[0], a[2]);
    swap(a[2], a[5]);
    swap(a[5], a[4]);
}

//上层顺时针旋转
void u(st &s) {
    ucell(s[0]);
    ucell(s[1]);
    ucell(s[2]);
    ucell(s[3]);
//    块的相对位置调换
    swap(s[1], s[0]);
    swap(s[2], s[1]);
    swap(s[3], s[2]);

}

//右层旋转是面的位置变化
void rcell(char *a) {
    swap(a[1], a[0]);
    swap(a[0], a[3]);
    swap(a[3], a[5]);
}

void r(st &s)//魔方右层顺时针转
{
    rcell(s[1]);
    rcell(s[2]);
    rcell(s[6]);
    rcell(s[5]);
//    块的位置变化
    swap(s[2], s[1]);
    swap(s[5], s[1]);
    swap(s[6], s[5]);
}

void fcell(char *a) {
    swap(a[2], a[1]);
    swap(a[1], a[4]);
    swap(a[4], a[3]);
}

void f(st &s)//前面一层 顺时针转
{
    fcell(s[0]);
    fcell(s[1]);
    fcell(s[4]);
    fcell(s[5]);
    swap(s[1], s[5]);
    swap(s[0], s[1]);
    swap(s[4], s[0]);
}

void uwhole(st &s)//整个魔方从顶部看 顺时针转 用于判重
{
    u(s);//上层旋转
//    下层旋转
    ucell(s[4]);
    ucell(s[5]);
    ucell(s[6]);
    ucell(s[7]);
//    完成自旋后,块的位置变动
    swap(s[5], s[4]);
    swap(s[6], s[5]);
    swap(s[7], s[6]);
}

void fwhole(st &s)//整个魔方从前面看 顺时针转 用于判重
{
    f(s);
    fcell(s[2]);
    fcell(s[6]);
    fcell(s[7]);
    fcell(s[3]);
    swap(s[2], s[6]);
    swap(s[3], s[2]);
    swap(s[7], s[3]);
}

void rwhole(st &s)//整个魔方从右边看 顺时针转 用于判重
{
    r(s);
    rcell(s[0]);
    rcell(s[3]);
    rcell(s[4]);
    rcell(s[7]);
    swap(s[3], s[7]);
    swap(s[0], s[3]);
    swap(s[4], s[0]);
}


bool try_insert(st &s) {
    st k;
    memcpy(k, s, sizeof(start));
    for (int i = 0; i < 4; i++) {
        fwhole(k);
        for (int j = 0; j < 4; j++) {
            uwhole(k);
            for (int q = 0; q < 4; q++) {
                rwhole(k);
                if (all_state.count(to_string(k)) == 1) {
                    return false;
                }
            }
        }
    }
    all_state.insert(to_string(k));
    return true;

}

void solve() {
    front = 0;
    tail = 1;
    all_state.insert(to_string(start));
    memcpy(q[front], start, sizeof(start));//填充q[0],相当于第一个状态入队列
    while (front < tail) {
        /*将其所有变形,尝试加入set中*/
        memcpy(q[tail], q[front], sizeof(start));//拷贝到tail
        u(q[tail]);//上层顺时针旋转
        if (try_insert(q[tail])) {
            tail++;//扩展队列
        }
        memcpy(q[tail], q[front], sizeof(start));//拷贝到tail
        r(q[tail]);//右层顺时针旋转
        if (try_insert(q[tail])) {
            tail++;//扩展队列
        }
        memcpy(q[tail], q[front], sizeof(start));//拷贝到tail
        f(q[tail]);//前顺时针旋转
        if (try_insert(q[tail])) {
            tail++;//扩展队列
        }
        front++;//弹出队首
//        cout << front << " " << tail << endl;
    }

    cout << front << endl;
}

int main(int argc, const char *argv[]) {
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/AlexKing007/p/12338592.html