HDU 5250 三阶魔方(很有意思的模拟题)

三阶魔方

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 123    Accepted Submission(s): 57


Problem Description
给定三阶魔方的基本操作:



现给出一个由基本操作组合成的操作序列,求问:对一个初状态(六个面都是拼好的)的魔方进行多少次连续的序列操作后,魔方会恢复到初状态。
 

Input
第一行为T,表示输入数据组数。

下面T行,每行给出一个合法的操作序列字符串,每行不超过100个字符。
 

Output
对第i组数据,输出

Case #i:

然后输出一个整数,表示答案。若魔方不会恢复则输出-1。
 

Sample Input
  
  
3 R2 R'R'U2 RU
 

Sample Output
  
  
Case #1: 2 Case #2: 6 Case #3: 105
 

Source
 

Recommend
hujie
 



题意:

给定一个操作序列,问执行多少次操作以后,魔方会恢复原状,如果不能则输出-1


思路:

很明显对于同一个操作执行多次肯定是可以还原的。
考虑魔方上的某一个面的一个点(标号为1),如果执行一次操作以后还在原来的位置,那么不管执行几次都在原来的位置。
如果不在原来的位置,例如1到了2的位置,2到了6的位置,6到了1的位置,那么执行三次操作以后就可以复原这三个点(相当于转了一圈)。

具体的做法是,我们可以执行一遍这个操作,找出所有的环,求出所有环长度的最小公倍数即可(想一想是不是很有道理呢)

为了简化编码,我们可以把U2变成UU,U‘变成UUU,这样只要编写6种操作就可以了。

怎么执行操作呢,每一个操作我们都要记录魔方当前的状态,如果使用3x3x3的坐标记录点的位置,那么将无法保存颜色信息(在哪一面),因此可以用3x3x6的数组保存6个面,在执行一个操作时(例如R),会涉及到5个面,即右,上、后、下、前,R顺时针旋转90度,其他的面每个只有3个数字会改变

代码写的比较长,个人感觉这样直观一些


#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
const int maxn=3e3+50;
const int Mod=1e9+7;
typedef long long ll;

using namespace std;


const int W=3;
int maze[6][W][W];

int hashId[100];
bool vis[100];

string get(char c,char t)
{
    string ret="";
    if (t=='2') return ret+c+c;
    if (t=='\'') return ret+c+c+c;
}
string expandCommand(string &s)
{

    string ret="";
    int sz=s.size();
    for (int i=0;i<sz;){
        if(i==sz-1 || (isalpha(s[i]) && isalpha(s[i+1]))) {
            ret+=s[i];
            i++;
        }
        else {
            ret+=get(s[i],s[i+1]);
            i+=2;
        }
    }
    return ret;
}

//0 1 2 3 4 5
//U D L R F B
void rotateClockwise(int face[W][W])
{
    int tmp[W][W];
    for (int i=0;i<W;i++)
        for(int j=0;j<W;j++){
            tmp[i][j]=face[W-j-1][i];
        }
    for (int i=0;i<W;i++){
        for(int j=0;j<W;j++){
         //   printf("%d ",tmp[i][j]);
            face[i][j]=tmp[i][j];
        }
       // puts("");
    }
}

void swapClockwise( int &s1,int &s2,int &s3,
            int &s4,int &s5,int &s6,
            int &s7,int &s8,int &s9,
            int &s10,int &s11,int &s12){
    int tmp[13];
    tmp[1]=s1; tmp[2]=s2; tmp[3]=s3;
    tmp[4]=s4; tmp[5]=s5; tmp[6]=s6;
    tmp[7]=s7; tmp[8]=s8; tmp[9]=s9;
    tmp[10]=s10; tmp[11]=s11; tmp[12]=s12;

    s1=tmp[10]; s2=tmp[11]; s3=tmp[12];
    s4=tmp[1]; s5=tmp[2]; s6=tmp[3];
    s7=tmp[4]; s8=tmp[5]; s9=tmp[6];
    s10=tmp[7]; s11=tmp[8]; s12=tmp[9];
}

inline int getR(int x){
    x--;
    return x/3;
}
inline int getC(int x){
    x--;
    return x%3;
}
void excute(string &s)
{

    int cnt=1;
    for (int i=0;i<6;i++){
        for(int j=0;j<W;j++)
            for (int k=0;k<W;k++)
                maze[i][j][k]=cnt++;
    }
    int sz=s.size();
    for (int i=0;i<sz;i++){
     //   printf("%d %c\n",i,s[i]);
        if (s[i]=='U'){
            //0 1 2 3 4 5
            //U D L R F B

            rotateClockwise(maze[0]);
            swapClockwise(
                maze[5][getR(3)][getC(3)],
                maze[5][getR(2)][getC(2)],
                maze[5][getR(1)][getC(1)],

                maze[3][getR(3)][getC(3)],
                maze[3][getR(2)][getC(2)],
                maze[3][getR(1)][getC(1)],

                maze[4][getR(3)][getC(3)],
                maze[4][getR(2)][getC(2)],
                maze[4][getR(1)][getC(1)],

                maze[2][getR(3)][getC(3)],
                maze[2][getR(2)][getC(2)],
                maze[2][getR(1)][getC(1)]

                );
        }else if (s[i]=='D'){
            //0 1 2 3 4 5
            //U D L R F B
            rotateClockwise(maze[1]);
            swapClockwise(
                maze[4][getR(7)][getC(7)],
                maze[4][getR(8)][getC(8)],
                maze[4][getR(9)][getC(9)],

                maze[3][getR(7)][getC(7)],
                maze[3][getR(8)][getC(8)],
                maze[3][getR(9)][getC(9)],

                maze[5][getR(7)][getC(7)],
                maze[5][getR(8)][getC(8)],
                maze[5][getR(9)][getC(9)],

                maze[2][getR(7)][getC(7)],
                maze[2][getR(8)][getC(8)],
                maze[2][getR(9)][getC(9)]
                );
        }else if (s[i]=='L'){
            //0 1 2 3 4 5
            //U D L R F B
            rotateClockwise(maze[2]);
            swapClockwise(
                maze[0][getR(1)][getC(1)],
                maze[0][getR(4)][getC(4)],
                maze[0][getR(7)][getC(7)],

                maze[4][getR(1)][getC(1)],
                maze[4][getR(4)][getC(4)],
                maze[4][getR(7)][getC(7)],

                maze[1][getR(1)][getC(1)],
                maze[1][getR(4)][getC(4)],
                maze[1][getR(7)][getC(7)],

                maze[5][getR(9)][getC(9)],
                maze[5][getR(6)][getC(6)],
                maze[5][getR(3)][getC(3)]
                );

        }else if (s[i]=='R'){
            //0 1 2 3 4 5
            //U D L R F B
            rotateClockwise(maze[3]);
            swapClockwise(
                maze[0][getR(9)][getC(9)],
                maze[0][getR(6)][getC(6)],
                maze[0][getR(3)][getC(3)],

                maze[5][getR(1)][getC(1)],
                maze[5][getR(4)][getC(4)],
                maze[5][getR(7)][getC(7)],

                maze[1][getR(9)][getC(9)],
                maze[1][getR(6)][getC(6)],
                maze[1][getR(3)][getC(3)],

                maze[4][getR(9)][getC(9)],
                maze[4][getR(6)][getC(6)],
                maze[4][getR(3)][getC(3)]
                );
        }else if (s[i]=='F'){
            //0 1 2 3 4 5
            //U D L R F B
            rotateClockwise(maze[4]);
            swapClockwise(
                maze[0][getR(7)][getC(7)],
                maze[0][getR(8)][getC(8)],
                maze[0][getR(9)][getC(9)],

                maze[3][getR(1)][getC(1)],
                maze[3][getR(4)][getC(4)],
                maze[3][getR(7)][getC(7)],

                maze[1][getR(3)][getC(3)],
                maze[1][getR(2)][getC(2)],
                maze[1][getR(1)][getC(1)],

                maze[2][getR(9)][getC(9)],
                maze[2][getR(6)][getC(6)],
                maze[2][getR(3)][getC(3)]
                );
        }else if (s[i]=='B'){
            //0 1 2 3 4 5
            //U D L R F B
            rotateClockwise(maze[5]);
            swapClockwise(
                maze[0][getR(3)][getC(3)],
                maze[0][getR(2)][getC(2)],
                maze[0][getR(1)][getC(1)],

                maze[2][getR(1)][getC(1)],
                maze[2][getR(4)][getC(4)],
                maze[2][getR(7)][getC(7)],

                maze[1][getR(7)][getC(7)],
                maze[1][getR(8)][getC(8)],
                maze[1][getR(9)][getC(9)],

                maze[3][getR(9)][getC(9)],
                maze[3][getR(6)][getC(6)],
                maze[3][getR(3)][getC(3)]
                );
        }
    }
    return;
}

void getHash(){
    int cnt=1;
    for (int i=0;i<6;i++){
        for(int j=0;j<W;j++)
            for (int k=0;k<W;k++){
                hashId[cnt++]=maze[i][j][k];
              //  printf("%d %d\n",cnt-1,hashId[cnt-1]);
            }
    }
}


ll gcd(ll a,ll b){
    return (b==0)? a:gcd(b,a%b);
}

int getCycle(vector<int> &v){
    mem(vis,0);
    for (int i=1;i<=36;i++){
        if (vis[i]) continue;
        int cnt=1,pos=i;
        vis[pos]=1;
        while(hashId[pos]!=i){
           // printf("pos:%d hashId:%d %d\n",pos,hashId[pos],i);
         //   getchar();
            pos=hashId[pos];
            vis[pos]=1;
            cnt++;
        }
     //   cout<<cnt<<'\n';
        v.push_back(cnt);
    }
}

ll LCM(vector<int> &v){
    ll ret=1;
    int sz=v.size();
    for (int i=0;i<sz;i++){
        ret=ret/gcd(ret,(ll)v[i])*v[i];
    }
    return ret;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    int n,T;
    string str;
    scanf("%d",&T);
    for (int cs=1;cs<=T;cs++){
        printf("Case #%d:\n",cs);
        cin>>str;
        string command=expandCommand(str);
       // cout<<command<<'\n';
        excute(command);
        getHash();
        vector<int> cycle;
        getCycle(cycle);
        printf("%lld\n",LCM(cycle));
    }
    return 0;
}



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值