2017蓝桥杯C++A组——魔方状态

魔方状态题目链接

问题描述

【题目描述】
在这里插入图片描述
【输出】
在这里插入图片描述

题目解析

在这里插入图片描述

  1. 定义 s t a r t start start这个初始状态, f r o n t front front头指针指向初始状态。
  2. 对这个初始状态分别做上层旋转、右层旋转、前层旋转,试图加入set集合中,如果之前从未出现过该序列则加入成功, t a i l tail tail尾指针++, f r o n t front front++;
  3. 不断重复步骤2直到 t a i l = = f r o n t tail==front tail==front,此时 f r o n t front front就表示加入的总状态数,即为所求。

C++代码

#include<bits/stdc++.h>
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[3]);
    rcell(s[0]);
    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)
    {
        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()
{
    solve();
    return 0;
}

正确答案

该代码跑出来需要一定时间,大家一定要耐心等待~
在这里插入图片描述
原文参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值