问题 1176: 【魔板】【借鉴】【注释版】

时间限制: 1Sec 内存限制: 128MB

题目描述

在魔方风靡全球之后不久,Rubik先生发明了它的简化版――魔板。魔板 由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示。任一时刻魔板的状态可用方块的颜色序列表示:从魔板的左上角开始,按顺时针方 向依次写下各方块的颜色代号,所得到的数字序列即可表示此时魔板的状态。例如,序列(1,2,3,4,5,6,7,8)表示魔板状态为:
1 2 3 4
8 7 6 5
对于魔板,可施加三种不同的操作,具体操作方法如下:
A: 上下两行互换,如上图可变换为状态87654321
B: 每行同时循环右移一格,如上图可变换为41236785
C: 中间4个方块顺时针旋转一格,如上图可变换为17245368
给你魔板的初始状态与目标状态,请给出由初态到目态变换数最少的变换步骤,若有多种变换方案则取字典序最小的那种。

输入
每组测试数据包括两行,分别代表魔板的初态与目态。

输出
对每组测试数据输出满足题意的变换步骤。

样例输入
12345678
17245368
12345678
82754631
样例输出
C
AC

Code

Code 0 借鉴自一位大牛

注释写好了,也终于弄懂了
首先是设置一个结构体,然后根据结构体定义一个很大的队列数组。
先来说说这个结构的成员:str用来存放魔板信息;opt当前魔板进行的操作;par前一步的操作在队列中的位置
然后就是每一种情况的代表关键字,这个地方很巧妙,从i=0到7,计算从第i个数开始后面的数大于第i个数的个数,然后乘以对应的阶乘。这个阶乘的作用就是拉大vi数组间隔的值。
通过队列的操作,每一步后都有三种可能,使用par就将这些操作连起来。

#include<stdio.h>
#include<string.h>
#define MAXN 40330 
#define MAXL 8
struct {
   
    char str[MAXL + 1];//存放魔板的数组
    char opt;//当前魔板进行的操作
    int par;//前一步的操作在队列中的位置
} queue[MAXN], tmp, nxt;
//阶乘:0  1   2   3   4   5   6   7
int fac[8] = {
    1, 1, 2, 6, 24, 120, 720, 5040 };//作用是什么?
int vis[MAXN];//访问函数
char opt[] = "ABC";//三种选择的数组
char aim[MAXL + 1];//目标魔板
void(*fun[3])(char *str);//定义三个单位大小的指针数组,用来存放三个变形函数的地址
//交换函数
void swap(char* a, char* b) {
   
    char tmp = *a;
    *a = *b;
    *b = tmp;
}
//三种变形函数
void optA(char* str) {
   
    swap(&str[0], &str[4]);
    swap(&str[1], &str[5]);
    swap(&str[2], &str[6]);
    swap(&str[3], &str[7]);
}
void optB(char* str) {
   
    int i;
    char tmp;
    for (tmp = str[3], i = 3; i > 0; --i) {
   
        str[i] = str[i - 1];
    }
    str[0] = tmp;
    for (tmp = str[7], i = 7; i > 4; --i) {
   
        str[i] = str[i - 1];
    }
    str[4] = tmp;
}
void optC(char* str) {
   
    char tmp = str[1];
    str[1] = str[5];
    str[5] = str[6];
    str[6] = str[2];
    str[2] = tmp;
}
//打印输出
void print(int k) {
   
    if (queue[k].par == -1) return;
    print(queue[k].par);
    printf("%c", queue[k].opt);
}

//哈希函数
//为什么要统计这个数据呢?或者说这个数据对检验重复的数据的作用是什么?
int hash(char *str){
   
    int i, j, cnt, sum = 0;
    for (i = 0; i < MAXL; ++i){
   
        for (cnt = 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值