时间限制: 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 =