Magic Cube ZOJ - 2477

题目链接:Magic Cube ZOJ - 2477

===================================================

Magic Cube

Time Limit: 2000MS
Memory Limit: 65536 kB

Description

This is a very popular game for children. In this game, there’s a cube, which consists of 3 * 3 * 3 small cubes. We can unwrap the cube, it will become like this:

  w w w
  w w w
  w w w

r r r g g g b b b o o o
r r r g g g b b b o o o
r r r g g g b b b o o o
y y y
y y y
y y y

The letters means the color on the small cubes. For example, ‘r’ means red, ‘g’ means green, ‘y’ means yellow…The goal for this game is to rotate the faces of the cube to make each of the faces contains only one color. Note there’re exact 6 kind of colors on the cube and there’re exact 9 small rectangles totally in any time in the game.

Do you know how to rotate the faces? I think most of you have known it. But I would like to show it again. When a face is rotated, the configuration of colors in all the adjacent faces changes. For the cube above, after we rotate the green face clock-wise, the last line of ‘w’ face will become the left column of ‘b’ face, the left column of ‘b’ face will become the top line of ‘y’ face, etc. As you may know, reaching the final position from a scrambled configuration can be quite challenging.

In this problem, you are given a configuration of the cube, and asked to give a way to reach the final position. To reduce the difficulty, the steps required will never be greater than 5.

Input

The input contains an integer in the first line, which indicates the number of the test cases. In each test case, there’re exact 10 lines. The first line is an empty line. The next 9 lines contain a configuration. The format can be seen in the sample input. For simplicity, we give an index to each face as follows:

/---\
|   |
| 4 |
|   |

/—±–±–±–
| | | | |
| 0 | 1 | 2 | 3 |
| | | | |
—±–±–±–/
| |
| 5 |
| |
—/

Note that there’s a space between two adjacent letters.

Output

For each test case, the first line of the output is the smallest count N of the steps to reach the winning position. If the winning position can’t be reached in 5 steps, print -1 in this line. Otherwise print each step in one line in the following N lines. A step contains two integers, the first one means the face index, and the second one means the direction. 1 means clock-wise and -1 means counter clock-wise. If the given position is the winning position, print 0 for such test case simply. If there’re multiple solutions, any one is acceptable.

Sample Input

2
w w w
w w w
w w w
r r r g g g b b b o o o
r r r g g g b b b o o o
r r r g g g b b b o o o
y y y
y y y
y y y

  w w w
  w w w
  b b b

r r w g g g y b b o o o
r r w g g g y b b o o o
r r w g g g y b b o o o
r r r
y y y
y y y

Sample Output

0
1
1 1

===================================================

算法:IDA* 优化dfs,普通dfs也能过

思路:

  • 最痛苦的一道题,大意都理解,问题出在细节。
  • limit给出了需要5步内,就直接从0开始慢慢加到5;
  • IDA启发函数就相当于最优情况下的估算步数+当前步数,这里你想,一个操作可最多改变3*4的单位(不考虑顺序)。所以你记录6个面不同与中心方格的数量,然后除以12,向上取整就是最优估算。
  • 剪枝就是不走前面一步同一面的反方向,比如(1,-1)与(1,1)会相互抵消效果

难点:开始了,最痛苦的细节,本题我出错的地方,方便那些不知道错误地方的同志留意。

  • 就是你转的那个面,它自身图案顺序会转动,模拟真实魔方就知道。
  • 题目给出颜色 rg什么的,不是判断标准,你要以输入的面中心方格颜色为标准。
  • 向上取整的ceil函数里面的数一定要是浮点型。。。。我哭了 wzc

===================================================

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>

using namespace std;

char mp[6][4][4];
int ans[6][3];

int check(){
    double ans = 0;
    for(int i=0;i<6;i++)
        for(int x=0;x<3;x++)
            for(int y=0;y<3;y++) if(mp[i][x][y]!=mp[i][1][1]) ans++;
    return ceil(ans/12);
}
//==================================================
void op2(int x,int y){
    if(y==-1){
        char ch = mp[x][0][0];mp[x][0][0] = mp[x][0][2];mp[x][0][2] = mp[x][2][2];
        mp[x][2][2] = mp[x][2][0];mp[x][2][0] = ch;
        ch = mp[x][0][1];mp[x][0][1] = mp[x][1][2];mp[x][1][2] = mp[x][2][1];
        mp[x][2][1] = mp[x][1][0];mp[x][1][0] = ch;
    }else{
        char ch = mp[x][0][0];mp[x][0][0] = mp[x][2][0];mp[x][2][0] = mp[x][2][2];
        mp[x][2][2] = mp[x][0][2];mp[x][0][2] = ch;
        ch = mp[x][0][1];mp[x][0][1] = mp[x][1][0];mp[x][1][0] = mp[x][2][1];
        mp[x][2][1] = mp[x][1][2];mp[x][1][2] = ch;
    }
}
void op(int x,int y){
    op2(x,y);
    switch(x){
        case 0:
            if(y==-1){
                char a = mp[4][0][0],b = mp[4][1][0],c = mp[4][2][0];
                mp[4][0][0] = mp[1][0][0];mp[4][1][0] = mp[1][1][0];mp[4][2][0] = mp[1][2][0];
                mp[1][0][0] = mp[5][0][0];mp[1][1][0] = mp[5][1][0];mp[1][2][0] = mp[5][2][0];
                mp[5][0][0] = mp[3][2][2];mp[5][1][0] = mp[3][1][2];mp[5][2][0] = mp[3][0][2];
                mp[3][0][2] = c;mp[3][1][2] = b;mp[3][2][2] = a;
            }else{
                char a = mp[4][0][0],b = mp[4][1][0],c = mp[4][2][0];
                mp[4][0][0] = mp[3][2][2];mp[4][1][0] = mp[3][1][2];mp[4][2][0] = mp[3][0][2];
                mp[3][2][2] = mp[5][0][0];mp[3][1][2] = mp[5][1][0];mp[3][0][2] = mp[5][2][0];
                mp[5][0][0] = mp[1][0][0];mp[5][1][0] = mp[1][1][0];mp[5][2][0] = mp[1][2][0];
                mp[1][0][0] = a;mp[1][1][0] = b;mp[1][2][0] = c;

            }break;

        case 1:
            if(y==-1){
                char a = mp[4][2][0],b = mp[4][2][1],c = mp[4][2][2];
                mp[4][2][0] = mp[2][0][0];mp[4][2][1] = mp[2][1][0];mp[4][2][2] = mp[2][2][0];
                mp[2][0][0] = mp[5][0][2];mp[2][1][0] = mp[5][0][1];mp[2][2][0] = mp[5][0][0];
                mp[5][0][2] = mp[0][2][2];mp[5][0][1] = mp[0][1][2];mp[5][0][0] = mp[0][0][2];
                mp[0][2][2] = a;mp[0][1][2] = b;mp[0][0][2] = c;
            }else{
                char a = mp[4][2][0],b = mp[4][2][1],c = mp[4][2][2];
                mp[4][2][0] = mp[0][2][2];mp[4][2][1] = mp[0][1][2];mp[4][2][2] = mp[0][0][2];
                mp[0][2][2] = mp[5][0][2];mp[0][1][2] = mp[5][0][1];mp[0][0][2] = mp[5][0][0];
                mp[5][0][2] = mp[2][0][0];mp[5][0][1] = mp[2][1][0];mp[5][0][0] = mp[2][2][0];
                mp[2][0][0] = a;mp[2][1][0] = b;mp[2][2][0] = c;
            }break;

        case 2:
            if(y==-1){
                char a = mp[4][0][2],b = mp[4][1][2],c = mp[4][2][2];
                mp[4][0][2] = mp[3][2][0];mp[4][1][2] = mp[3][1][0];mp[4][2][2] = mp[3][0][0];
                mp[3][2][0] = mp[5][0][2];mp[3][1][0] = mp[5][1][2];mp[3][0][0] = mp[5][2][2];
                mp[5][0][2] = mp[1][0][2];mp[5][1][2] = mp[1][1][2];mp[5][2][2] = mp[1][2][2];
                mp[1][0][2] = a;mp[1][1][2] = b;mp[1][2][2] = c;
            }else{
                char a = mp[4][0][2],b = mp[4][1][2],c = mp[4][2][2];
                mp[4][0][2] = mp[1][0][2];mp[4][1][2] = mp[1][1][2];mp[4][2][2] = mp[1][2][2];
                mp[1][0][2] = mp[5][0][2];mp[1][1][2] = mp[5][1][2];mp[1][2][2] = mp[5][2][2];
                mp[5][0][2] = mp[3][2][0];mp[5][1][2] = mp[3][1][0];mp[5][2][2] = mp[3][0][0];
                mp[3][2][0] = a;mp[3][1][0] = b;mp[3][0][0] = c;
            }break;

        case 3:
            if(y==-1){
                char a = mp[4][0][0],b = mp[4][0][1],c = mp[4][0][2];
                mp[4][0][0] = mp[0][2][0];mp[4][0][1] = mp[0][1][0];mp[4][0][2] = mp[0][0][0];
                mp[0][2][0] = mp[5][2][2];mp[0][1][0] = mp[5][2][1];mp[0][0][0] = mp[5][2][0];
                mp[5][2][2] = mp[2][0][2];mp[5][2][1] = mp[2][1][2];mp[5][2][0] = mp[2][2][2];
                mp[2][0][2] = a;mp[2][1][2] = b;mp[2][2][2] = c;
            }else{
                char a = mp[4][0][0],b = mp[4][0][1],c = mp[4][0][2];
                mp[4][0][0] = mp[2][0][2];mp[4][0][1] = mp[2][1][2];mp[4][0][2] = mp[2][2][2];
                mp[2][0][2] = mp[5][2][2];mp[2][1][2] = mp[5][2][1];mp[2][2][2] = mp[5][2][0];
                mp[5][2][2] = mp[0][2][0];mp[5][2][1] = mp[0][1][0];mp[5][2][0] = mp[0][0][0];
                mp[0][2][0] = a;mp[0][1][0] = b;mp[0][0][0] = c;
            }break;

        case 4:
            if(y==-1){
                char a = mp[3][0][0],b = mp[3][0][1],c = mp[3][0][2];
                mp[3][0][0] = mp[2][0][0];mp[3][0][1] = mp[2][0][1];mp[3][0][2] = mp[2][0][2];
                mp[2][0][0] = mp[1][0][0];mp[2][0][1] = mp[1][0][1];mp[2][0][2] = mp[1][0][2];
                mp[1][0][0] = mp[0][0][0];mp[1][0][1] = mp[0][0][1];mp[1][0][2] = mp[0][0][2];
                mp[0][0][0] = a;mp[0][0][1] = b;mp[0][0][2] = c;
            }else{
                char a = mp[3][0][0],b = mp[3][0][1],c = mp[3][0][2];
                mp[3][0][0] = mp[0][0][0];mp[3][0][1] = mp[0][0][1];mp[3][0][2] = mp[0][0][2];
                mp[0][0][0] = mp[1][0][0];mp[0][0][1] = mp[1][0][1];mp[0][0][2] = mp[1][0][2];
                mp[1][0][0] = mp[2][0][0];mp[1][0][1] = mp[2][0][1];mp[1][0][2] = mp[2][0][2];
                mp[2][0][0] = a;mp[2][0][1] = b;mp[2][0][2] = c;
            }break;

        case 5:
            if(y==-1){
                char a = mp[1][2][0],b = mp[1][2][1],c = mp[1][2][2];
                mp[1][2][0] = mp[2][2][0];mp[1][2][1] = mp[2][2][1];mp[1][2][2] = mp[2][2][2];
                mp[2][2][0] = mp[3][2][0];mp[2][2][1] = mp[3][2][1];mp[2][2][2] = mp[3][2][2];
                mp[3][2][0] = mp[0][2][0];mp[3][2][1] = mp[0][2][1];mp[3][2][2] = mp[0][2][2];
                mp[0][2][0] = a;mp[0][2][1] = b;mp[0][2][2] = c;
            }else{
                char a = mp[1][2][0],b = mp[1][2][1],c = mp[1][2][2];
                mp[1][2][0] = mp[0][2][0];mp[1][2][1] = mp[0][2][1];mp[1][2][2] = mp[0][2][2];
                mp[0][2][0] = mp[3][2][0];mp[0][2][1] = mp[3][2][1];mp[0][2][2] = mp[3][2][2];
                mp[3][2][0] = mp[2][2][0];mp[3][2][1] = mp[2][2][1];mp[3][2][2] = mp[2][2][2];
                mp[2][2][0] = a;mp[2][2][1] = b;mp[2][2][2] = c;
            }break;
    }
}
//================================================
int dfs(int step,int prex,int prey,int limit){
    int h = check();
    if(step+h>limit) return 0;
    if(h==0) return 1;
    for(int i=0;i<6;i++)
        for(int j=0,z=-1;j<2;j++,z+=2){
            if(prex == i && prey+z == 0) continue;
            op(i,z);
            if(dfs(step+1,i,z,limit)) {ans[step][0]=i,ans[step][1]=z;return 1;}
            op(i,-z);
        }
    return 0;
}
//================================================
int main()
{
    int _;scanf("%d",&_);
    while(_--){
        char ch;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++){
                ch = getchar();while(ch=='\n'||ch==' ') ch=getchar();
                mp[4][i][j] = ch;
            }
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                ch = getchar();while(ch=='\n'||ch==' ') ch=getchar();
                mp[0][i][j] = ch;
            }
            for(int j=0;j<3;j++){
                ch = getchar();while(ch=='\n'||ch==' ') ch=getchar();
                mp[1][i][j] = ch;
            }
            for(int j=0;j<3;j++){
                ch = getchar();while(ch=='\n'||ch==' ') ch=getchar();
                mp[2][i][j] = ch;
            }
            for(int j=0;j<3;j++){
                ch = getchar();while(ch=='\n'||ch==' ') ch=getchar();
                mp[3][i][j] = ch;
            }
        }
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                ch = getchar();while(ch=='\n'||ch==' ') ch=getchar();
                mp[5][i][j] = ch;
            }
        }
        int limit;
        for(limit = 0;limit<6;limit++)
            if(dfs(0,-1,0,limit)==1){
                printf("%d\n",limit);
                for(int i=0;i<limit;i++) printf("%d %d\n",ans[i][0],ans[i][1]);
                break;
            }
        if(limit == 6) puts("-1");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盐太郎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值