解密游戏 | 第十届蓝桥杯国赛C++B组

小明正在玩一款解谜游戏。

QQ截图20200930110941.png

谜题由 24 根塑料棒组成,其中黄色塑料棒 4根,红色 8 根,绿色 12 根 (后面用 Y 表示黄色、R表示红色、G 表示绿色)。

初始时这些塑料棒排成三圈,如上图所示,外圈 12 根,中圈 8根,内圈 4 根。

小明可以进行三种操作:

  1. 将三圈塑料棒都顺时针旋转一个单位。例如当前外圈从 0 点位置开始顺时针依次是 YRYGRYGRGGGG,中圈是 RGRGGRRY,内圈是 GGGR。那么顺时针旋转一次之后,外圈、中圈、内圈依次变为:GYRYGRYGRGGGYRGRGGRR 和 RGGG
  2. 将三圈塑料棒都逆时针旋转一个单位。例如当前外圈从 0 点位置开始顺时针依次是 YRYGRYGRGGGG,中圈是 RGRGGRRY,内圈是 GGGR。那么逆时针旋转一次之后,外圈、中圈、内圈依次变为:RYGRYGRGGGGYGRGGRRYR 和 GGRG
  3. 将三圈 0 点位置的塑料棒做一个轮换。具体来说:外圈 0 点塑料棒移动到内圈 0 点,内圈 0 点移动到中圈 0 点,中圈 0 点移动到外圈 0 点。例如当前外圈从 0 点位置开始顺时针依次是 YRYGRYGRGGGG,中圈是 RGRGGRRY,内圈是 GGGR。那么轮换一次之后,外圈、中圈、内圈依次变为:RRYGRYGRGGGGGGRGGRRY 和 YGGR

小明的目标是把所有绿色移动到外圈、所有红色移动中圈、所有黄色移动到内圈。

给定初始状态,请你判断小明是否可以达成目标?

输入格式

第一行包含一个整数 T,代表询问的组数。

每组询问包含 33行:

第一行包含 12个大写字母,代表外圈从 0 点位置开始顺时针每个塑料棒的颜色。

第二行包含 8 个大写字母,代表中圈从 0 点位置开始顺时针每个塑料棒的颜色。

第三行包含 4 个大写字母,代表内圈从 0 点位置开始顺时针每个塑料棒的颜色。

输出格式

对于每组询问,输出一行 YES 或者 NO,代表小明是否可以达成目标。

数据范围

1≤T≤100

输入样例:
2
GYGGGGGGGGGG
RGRRRRRR
YRYY
YGGGRRRRGGGY
YGGGRRRR
YGGG
输出样例:
YES
NO
题解:

        观察题目,发现以下几点:1.每经过24次转动,如果不变化顺序,则回到初始状态。

        2.每次进行0位置顺序变化,每次进行变化的相对位置是已知的。

                例:GYRY  RGGR  YRGG

                       RGGG  GGRG

                       GRYR

                发现如果在第二位置开始变化,选取的条子就是上面加粗的条子中选取,比如YGR、GGR、RGR...即第0位置的选取的条子池是固定的,是树形的。

        继续研究发现:

        选取出这几个条子,如果颜色数量是准确的,则一定可以按规定顺序排列。

        即:Y  G  R                                 G  G  G

                 G  G             -->                  R  R

                    R                                          Y

        证明:

        前提1:当三个位置上存在重复的颜色,比如RGR,则变换可视为任意两个颜色位置的交换。

                例:G            G                           R               G

                       G   ->     R                           G    ->      R

                       R            G                           R                R

                (即第二行和第三行交换)     (即第一行和第二行交换)

        前提2:当Y不在第三行的唯一位置时,一定存在其他所有列都存在重复颜色。

        所以,如果Y不在第三行,则通过其他列使某一列出现“RYG” “YGR”的顺序,其他位置都正确的情况,则变换目标列顺序即可达成目标,即使对应位置颜色正确。

        如果Y在第三行,则先将Y移出当前位置,再进行上述操作。

        结论:让三个环不能完成颜色分类的唯一情况就是选取的颜色数量不正确,比如有4个G。

代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>  
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;

int t=0;
string s1,s2,s3;
//s1外圈s2中圈s3内圈

string change(string s){
    char a1=s[0];
    string a2=s.substr(1,s.size()-1);
    //cout << a2 << "\n";
    string out=a2+a1;
    return out;
}

int judge(string s1,string s2,string s3){
    if((s1[0]=='R' && s2[0]=='Y' && s3[0]=='G') || (s1[0]=='Y' && s2[0]=='G' && s3[0]=='R')){
        return 1;
    }
    return 0;
}

int main(){
    cin >> t;
    while(t>0){
        cin >> s1 >> s2 >> s3;
        //cout << change(s1) << "\n";
        int ans=1;
        for(int i=0;i<4;i++){
            map<char,int> mp;
            mp['R']=0;mp['G']=0;mp['Y']=0;
            mp[s1[i]]++;
            mp[s1[i+4]]++;
            mp[s1[i+8]]++;
            mp[s2[i]]++;
            mp[s2[i+4]]++;
            mp[s3[i]]++;
            if(mp['R']!=2 || mp['Y']!=1 || mp['G']!=3){
                ans=0;
                break;
            }
        }
        if(ans){
            cout << "YES" << "\n";
        }
        else{
            cout << "NO" << "\n";
        }
        t--;
    }
}