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;
}

正确答案

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

### 蓝桥杯 C++ A 题目 解题思路 学习资料 蓝桥杯竞赛作为一项全国性的编程赛事,其A题目相较于B难度更高,涉及的知识面更广,通常需要选手具备扎实的数据结构与算法基础以及熟练掌握STL的能力。以下是关于蓝桥杯C++ A的相关题目、解题思路及学习资源的详细介绍。 #### 一、蓝桥杯C++ A常见考点 蓝桥杯A试题主要考察以下几个方面: - **数据结构**:链表、树、图等高级数据结构的应用[^1]。 - **动态规划**:复杂的状态转移方程设计和优化技巧[^2]。 - **贪心算法**:通过局部最优策略实现全局最优解决方案[^3]。 - **搜索算法**:深度优先搜索(DFS)、广度优先搜索(BFS),并结合剪枝技术提高效率。 - **数论知识**:质因数分解、同余定理及其应用等问题。 #### 二、典型题目解析 以下是一些可能出现在蓝桥杯C++ A中的经典问题类型: ##### 1. 数据结构综合运用 此类题目往往要求构建复杂的数据模型来解决问题。例如,在处理大规模输入时,可以利用哈希表加速查询过程;或者针对特定场景下的路径寻找问题,则需借助堆栈或队列完成遍历操作。 ```cpp // 使用STL容器解决实际问题的例子 #include <bits/stdc++.h> using namespace std; int main(){ vector<int> nums = { /* 初始化向量 */ }; sort(nums.begin(), nums.end()); // 对数进行排序 int target; cin >> target; auto it = lower_bound(nums.begin(), nums.end(), target); // 查找第一个不小于目标值的位置 } ``` ##### 2. 动态规划实例 对于某些计数类或多阶段决策型问题,采用动态规划方法能够有效降低时间复杂度。下面给出一个简单的背包问题代码片段用于说明如何定义dp数以及更新规则。 ```cpp const int MAXN=1e5+7,MAXV=1000; long long dp[MAXV]; for(int i=1;i<=n;i++) { for (int j=m;j>=w[i];j--) dp[j]=max(dp[j],dp[j-w[i]]+v[i]); } cout<<dp[m]<<endl;// 输出最大价值 ``` #### 三、推荐学习材料 为了更好地准备蓝桥杯C++ A比赛,建议参考如下书籍与在线课程: - 《算法导论》——全面覆盖各类核心算法理论。 - LeetCode刷题网站 —— 提供丰富的练习机会以巩固所学知识点。 - 牛客网上的历年真题讲解视频 —— 帮助理解官方解答背后的逻辑思维模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值