zoukankan      html  css  js  c++  java
  • zznu-2183: 口袋魔方

    大致题意:

    题目描述
    
    口袋魔方又称为迷你魔方,通俗的来讲就是二阶魔方,只有八个角块的魔方,如图所示。
    二阶魔方8个角块的位置均可进行任意互换(8!种状态),如果以一个角块不动作为参考角块,其他7个
    角块都能任意转换方向(即37种状态)。如果在空间中旋转则不计算方向不同而状态相同的魔方,实际上的准确
    状态数还应除以24。所以二阶魔方的总状态数为: 7!*3^6=3674160。二阶魔方的最远复原距离(即最需要最多
    步骤复原的状态)为11次全旋转,或者14次普通旋转,此结果可以用暴力穷举算法计算出
    下面给你一个口袋魔方,只需要进行一些简单的处理就能解决这道题了。对于此魔方的任意一个面,你可以选择
    顺时针旋转或者逆时针进行一次90度的旋转,如果能够进行不超过一次的旋转操作,就能使此魔方复原(每面内
    部颜色相同,共六种颜色),那么请输出“我真是个小机灵鬼!”,否则请输出“这个魔方有bug!”。
    
    
    输入
    
    第一行一个T,代表测试实例数。
    每个测试实例有6行输入。
    每行4个整数,代表相应位置的颜色
    输入数字位置对应下面魔方展开图。
    如a代表输入的第一个整数所在位置,其他同上。
    + - + - + - + - + - + - +
    | q  | r  | a  | b  | u | v  |
    + - + - + - + - + - + - +
    | s  | t  | c  | d  | w  | x  |
    + - + - + - + - + - + - +
               | e  | f  |
               + - + - +
               | g  | h |
               + - + - +
               | i   | j  |
               + - + - +
               | k  | l  |
               + - + - +
               | m | n |
               + - + - +
               | o  | p |
               + - + - +
    
    输出
    
    如题。
    样例输入
    
    4
    1 1 1 1
    2 2 2 2
    3 3 3 3
    4 4 4 4
    5 5 5 5
    6 6 6 6
    6 6 6 6
    1 1 1 1
    2 2 2 2
    3 3 3 3
    5 5 5 5
    4 4 4 4
    1 4 1 4
    2 1 2 1
    3 2 3 2
    4 3 4 3
    5 5 5 5
    6 6 6 6
    1 3 1 3
    2 4 2 4
    3 1 3 1
    4 2 4 2
    5 5 5 5
    6 6 6 6
    
    样例输出
    
    我真是个小机灵鬼!
    我真是个小机灵鬼!
    我真是个小机灵鬼!
    这个魔方有bug!
    View Code (已折叠! )

    大致思路:

    1.枚举全部地旋转方法,共八种: 顺时针 : 横一层/横二层/竖一层/竖二层 / 侧一层/侧二层

    同时逆时针,全部都对应一个;共16种!

    2. 每次旋转,只转动一层的八个格点而已 ; 八个格点只需要顺序或者逆序排序一下然后赋值即可!

    3.每旋转一次, 每个面上相邻的两个不用考虑顺序,因为这两个毕竟顺着方向上的旋转下是绑定在一起的!

    4/繁琐的东西用函数实现, 把一个大问题化解成小问题!

    5/注意把他们展开后,记得画图!用线顺时针在平面图上用线顺时针连起来! 后面的那个格子上下是颠倒的!串线的时候需要注意三维空间的真实情况!!

    题解:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define inf 0x3f3f3f3f
      4 #define N 50008
      5 #define ll long long
      6 #define mem(a,x) memset(a,x,sizeof(a))  ///问题 C: 签到(sign)
      7 int a[100];  //存每个面的颜色
      8 int mp1[10][10]={
      9     {1,2,3,4},
     10     {5,6,7,8},
     11     {9,10,11,12},
     12     {13,14,15,16},
     13     {17,18,19,20},
     14     {21,22,23,24}
     15 };
     16 int mp2[10][10]={
     17     {17,18,1,2,21,22,11,12},   //y=1&2
     18     {19,20,3,4,23,24,9,10},
     19     {1,3,5,7,9,11,13,15},  //rotate(),x=1&x=2
     20     {2,4,6,8,10,12,14,16},
     21     {18,20,15,16,21,23,5,6},
     22     {17,19,13,14,22,24,7,8}
     23 };
     24 
     25 void Rotate(int k,int mode){   //转动第k行mp2[]的列表  ,mode=0顺,mode=1表示逆
     26     vector<int>ans;
     27     for(int i=0;i<8;i++){
     28         int x=mp2[k][i];
     29         ans.push_back(a[x]);
     30     }
     31 
     32     if(mode==0){
     33         ans.push_back(ans[0]);
     34         ans.push_back(ans[1]);
     35         ans.erase(ans.begin(),ans.begin()+2);
     36 
     37          for(int i=0;i<8;i++){
     38             int x=mp2[k][i];
     39             a[x]=ans[i];
     40         }
     41     }
     42     else{
     43         int x=ans[7],y=ans[6];
     44         ans.insert(ans.begin(),x);
     45         ans.insert(ans.begin(),y);
     46         ans.erase(ans.end()-2,ans.end());
     47          for(int i=0;i<8;i++){
     48             int x=mp2[k][i];
     49             a[x]=ans[i];
     50         }
     51     }
     52 }
     53 bool judge(){
     54     for(int i=0;i<6;i++){
     55         int mx=-10000,minn=inf;
     56         for(int j=0;j<4;j++){
     57             int x=mp1[i][j];
     58             mx=max(mx,a[x]);
     59             minn=min(minn,a[x]);
     60         }
     61         if(mx!=minn)return 0;
     62     }
     63     return 1;
     64 }
     65 //void debug(){
     66 //    printf("%3d %3d %3d %3d %3d %3d
    ",a[17],a[18],a[1],a[2],a[21],a[22]);
     67 //    printf("%3d %3d %3d %3d %3d %3d
    ",a[19],a[20],a[3],a[4],a[23],a[24]);
     68 //    printf("        %3d %3d
            %3d %3d
    ",a[5],a[6],a[7],a[8]);
     69 //    printf("        %3d %3d
            %3d %3d
    ",a[9],a[10],a[11],a[12]);
     70 //    printf("        %3d %3d
            %3d %3d
    ",a[13],a[14],a[15],a[16]);
     71 //    printf("________
    ");
     72 //}
     73 void debug(){
     74     cout<<endl;
     75     for(int i=1;i<=24;i++)
     76         printf("%d%c",a[i],i%4==0?'
    ':' ');
     77     cout<<endl;
     78 }
     79 int main(){
     80     int T;
     81     scanf("%d",&T);
     82     while(T--){
     83         a[0]=-1;
     84         for(int i=1;i<=24;i++)
     85             scanf("%d",&a[i]);
     86 
     87 //        bool f=0;
     88 //        for(int i=0;!f&&i<6;i++)  //mode=0
     89 //            {
     90 //                Rotate(i,0);
     91 //                if(judge()==1)f=1;debug();
     92 //                Rotate(i,1);
     93 //                Rotate(i,1);
     94 //                if(judge()==1)f=1;debug();
     95 //                Rotate(i,0);
     96 //              //  if(judge()==0)printf("i1=%d,66666666
    ",i);
     97 //            }
     98 
     99         if(judge()==1){
    100             printf("我真是个小机灵鬼!
    ");
    101         }
    102         else{
    103             bool f=0;
    104             for(int i=0;!f&&i<6;i++)  //mode=0
    105             {
    106                 Rotate(i,0);
    107                 if(judge()==1)f=1;
    108                 Rotate(i,1);
    109               //  if(judge()==0)printf("i1=%d,66666666
    ",i);
    110             }
    111             for(int i=0;!f&&i<6;i++)   //mode=1
    112             {
    113                 Rotate(i,1);
    114                 if(judge()==1)f=1;
    115                 Rotate(i,0);
    116              //   if(judge()==0)printf("i1=%d,66666666
    ",i);
    117             }
    118             if(!f)
    119                 printf("这个魔方有bug!
    ");
    120             else
    121                 printf("我真是个小机灵鬼!
    ");
    122         }
    123     }
    124 
    125     return 0;
    126 }
    View Code(简洁思路版!)

    当然,我第一次不是这么写的!我是把所有的16种情况,每种情况单写一个函数解决的!

    写到第8个时,发现正着和逆着旋转某个角度其实可以化简,就回头看看,加了个op=-1!

    题解:(写了六个小时!!)

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define inf 0x3f3f3f3f
    #define N 110
    char str[N];
    
    ///第一维表示魔方的面
    int mp[10][20]=
    {
        {1,2,2, 2,2,2, 1,1,2, 2,1,2},  ///总共六个面,下标0-5  face_id
        {1,1,2, 2,1,2, 1,1,1, 2,1,1},
        {1,1,1, 2,1,1, 1,2,1, 2,2,1},
        {1,2,1, 2,2,1, 1,2,2, 2,2,2},
        {1,2,1, 1,2,2, 1,1,1, 1,1,2},
        {2,2,2, 2,2,1, 2,1,2, 2,1,1}
    };
    
    struct node{
        int x,y,z,Face;
        node(int x=0,int y=0,int z=0,int Face=0):x(x),y(y),z(z),Face(Face){}
    };
    
    
    int a[10][10][10][10];   ///四维对应 x-y-z- face_id
    
    bool judge()  ///判断是否达成魔方的要求
    {
        for(int i=0; i<=5; i++) //总共六个面
        {
            int minn=999,maxx=-1;
            for(int j=1; j<=4; j++)
            {
                int x=mp[i][j*3-3];
                int y=mp[i][j*3-2];
                int z=mp[i][j*3-1];
               minn=min(minn, a[x][y][z][i]);
               maxx=max(maxx, a[x][y][z][i]);
            }
            if(minn!=maxx)return false;
        }
        return true;
    }
    void debug(vector<int>st,int mode){
        cout<<"_______________***"<<"mode="<<mode<<endl;
        for(int i=0; i<=5; i++) //总共六个面
            {
                for(int j=1; j<=4; j++)
                {
                    int x=mp[i][j*3-3];
                    int y=mp[i][j*3-2];
                    int z=mp[i][j*3-1];
                    cout<<a[x][y][z][i]<<" ";  ///四维对应 x-y-z- face_id
                }
                cout<<endl;
            }
    
        cout<<"***"<<"st_list__"<<endl;
        for(int i=0;i<(int)st.size();i++){
            if((i+1)%4==0)
                printf(" %d **
    ",st[i]);
            else
                printf(" %d",st[i]);
        }
        cout<<endl;
    }
    void rotating(int mode){
    
        vector<int>st;
        int op=1;
        if(mode==0||mode==1){
           for(int i=0; i<=3; i++) //总共六个面
            {
                for(int j=1; j<=4; j+=2)
                {
                    int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                    st.push_back(a[x][y][z][i]);
                }
            }
            int len=st.size(),cnt=0;
    
        if(mode==1)op=-1;
            for(int i=0; i<=3; i++) //总共4个面,只取两个即可
            {
                for(int j=1; j<=4; j+=2)
                {
                    int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                    a[x][y][z][i] = st[(cnt-2*op+len)%len] ; ///x=1的四块,shun/ni时针
                    cnt++;
                }
            }
        }
    
        else if(mode == 2 || mode==3){
            for(int i=0; i<=3; i++){ //总共4个面
                for(int j=2; j<=4; j+=2){
                    int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                    st.push_back(a[x][y][z][i]);
                }
            }
            int len=st.size(),cnt=0;
    
        if(mode==3)op=-1;
            for(int i=0; i<=3; i++){ //总共4个面,只取两个即可
                for(int j=2; j<=4; j+=2){
                   int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                    a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///x=2的四块,shun/ni时针
                    cnt++;
                }
            }
        }
        else if(mode==4||mode==5){
            int ii[]={0,5,2,4};
             for(int k=0; k<=3; k++){ //总共4个面
                 if(ii[k]==2){
                     for(int j=1; j<=2; j++){
                            int i=ii[k];
                        int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                        st.push_back(a[x][y][z][i]);
                    }
                    continue;
                 }
                for(int j=3; j<=4; j++){
                        int i=ii[k];
                    int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                    st.push_back(a[x][y][z][i]);
                }
            }
            int len=st.size(),cnt=0;
    
        if(mode==5)op=-1;
            for(int k=0; k<=3; k++){ //总共4个面,只取两个即可
                if(ii[k]==2){
                     for(int j=1; j<=2; j++){
                            int i=ii[k];
                        int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                        a[x][y][z][i] = st[(cnt+2*op+len)%len] ;
                        cnt++;
                    }
                    continue;
                 }
                for(int j=3; j<=4; j++){
                    int i=ii[k];
                    int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                    a[x][y][z][i] = st[(cnt+2*op+len)%len] ;///y=1的四块,shun/ni时针
                    cnt++;
                }
            }
        }
    
        else if(mode==6||mode==7){        ///y=2,   3,4,1,2
             int ii[]={0,5,2,4};
             for(int k=0; k<=3; k++){ //总共4个面
                 if(ii[k]==2){
                     for(int j=3; j<=4; j++){
                            int i=ii[k];
                        int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                        st.push_back(a[x][y][z][i]);
                    }
                    continue;
                 }
                for(int j=1; j<=2; j++){
                        int i=ii[k];
                    int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                    st.push_back(a[x][y][z][i]);
                }
            }
            int len=st.size(),cnt=0;
    
        if(mode==7)op=-1;
            for(int k=0; k<=3; k++){ //总共4个面,只取两个即可
                if(ii[k]==2){
                     for(int j=3; j<=4; j++){
                            int i=ii[k];
                        int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                        a[x][y][z][i] = st[(cnt+2*op+len)%len] ;
                        cnt++;
                    }
                    continue;
                 }
                for(int j=1; j<=2; j++){
                    int i=ii[k];
                    int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                    a[x][y][z][i] = st[(cnt+2*op+len)%len] ;///y=2的四块,shun/ni时针
                    cnt++;
                }
            }
    
        }
        else if(mode==8||mode==9){
    
        if(mode==9) op=-1;
            for(int j=3; j<=4; j++){
                 int i=1;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 st.push_back(a[x][y][z][i]);
                }
            for(int j=2; j<=4; j+=2){
                 int i=5;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 st.push_back(a[x][y][z][i]);
            }
            for(int j=1; j<=2; j++){
                 int i=3;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 st.push_back(a[x][y][z][i]);
            }
             for(int j=1; j<=3; j+=2){
                 int i=4;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 st.push_back(a[x][y][z][i]);
            }
    
            int len=st.size(),cnt=0;
            for(int j=3; j<=4; j++){
                 int i=1;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///z=1的四块,shun/逆时针
                    cnt++;
                }
            for(int j=2; j<=4; j+=2){
                 int i=5;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///z=1的四块,shun/逆时针
                    cnt++;
            }
            for(int j=1; j<=2; j++){
                 int i=3;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///z=1的四块,shun/逆时针
                    cnt++;
            }
             for(int j=1; j<=3; j+=2){
                 int i=4;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///z=1的四块,shun/逆时针
                    cnt++;
            }
        }
        else if(mode==10||mode==11){
    
        if(mode==11)op=-1;
            for(int j=1; j<=2; j++){
                 int i=1;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 st.push_back(a[x][y][z][i]);
                }
            for(int j=1; j<=3; j+=2){
                 int i=5;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 st.push_back(a[x][y][z][i]);
            }
            for(int j=3; j<=4; j++){
                 int i=3;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 st.push_back(a[x][y][z][i]);
            }
             for(int j=2; j<=4; j+=2){
                 int i=4;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 st.push_back(a[x][y][z][i]);
            }
    
            int len=st.size(),cnt=0;
            for(int j=1; j<=2; j++){
                 int i=1;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///z=2的四块,shun/逆时针
                    cnt++;
                }
            for(int j=1; j<=3; j+=2){
                 int i=5;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///z=2的四块,shun/逆时针
                    cnt++;
            }
            for(int j=3; j<=4; j++){
                 int i=3;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///z=2的四块,shun/逆时针
                    cnt++;
            }
             for(int j=2; j<=4; j+=2){
                 int i=4;
                 int x=mp[i][j*3-3];int y=mp[i][j*3-2];int z=mp[i][j*3-1];
                 a[x][y][z][i] = st[(cnt-2*op+len)%len] ;///z=2的四块,shun/逆时针
                    cnt++;
            }
    
        }
    
       // debug(st,mode);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            for(int i=0; i<=5; i++) //总共六个面
            {
                for(int j=1; j<=4; j++)
                {
                    int x=mp[i][j*3-3];
                    int y=mp[i][j*3-2];
                    int z=mp[i][j*3-1];
                    cin>>a[x][y][z][i];  ///四维对应 x-y-z- face_id
                }
            }
    //        vector<int>st;
    //        debug(st,-1);
    
            if(judge()==true)
            {
                printf("我真是个小机灵鬼!
    ");
            }
            else
            {
                bool ans=false;
    
                for(int i=0;i<12&&!ans;i++)
                    {
                        rotating(i);
                        ans=judge();
                        rotating(i^1);  //旋转回去
                    }
                if(ans)
                     printf("我真是个小机灵鬼!
    ");
                else
                    printf("这个魔方有bug!
    ");
            }
        }
    
        return 0;
    }
    
    //        for(int i=0;i<=11;i++){
    //                int test=i;
    //            rotating(test);rotating(test^1);rotating(test^1);rotating(test);
    //            ///test成功:0,1,2, 3,4,5,6,7,8,9 ,
    //            if(judge()==true)
    //            {
    //                printf("Test %d OK!
    ",test);
    //            }
    //            else{
    //                printf("%d False!
    ",test);
    //            }
    //            continue;
    //        }
            //rotating(0);rotating(0^1); //测试成功
            //rotating(2);rotating(3); ///测试成功
          //  rotating(4);rotating(4^1); ///测试成功
           // rotating(6);rotating(6^1); ///测试成功
         //   rotating(10);rotating(10^1); ///测试成功 ,对一个正确的解,同一个层面顺拧一次、反拧一次必定正确
    
          //  rotating(2^1);
          //  cout<<"^1= "<<(2^1)<<endl;
    View Code
    你不逼自己一把,你永远都不知道自己有多优秀!只有经历了一些事,你才会懂得好好珍惜眼前的时光!
  • 相关阅读:
    移动 App 接入 QQ 登录/分享 图文教程
    Word 最后一页无法删除-解决办法
    Java快速入门-04-Java.util包简单总结
    Java快速入门-03-小知识汇总篇(全)
    SSM 框架-06-详细整合教程(IDEA版)(Spring+SpringMVC+MyBatis)
    二叉树的镜像
    浅析I/O模型及其设计模式
    远程方法调用(RMI)原理与示例
    树的子结构
    合并两个排序的链表
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/9769015.html
Copyright © 2011-2022 走看看