【HDU-1430】解题报告(数论,康拓展开逆展开,简单哈希,BFS)
原始题目
魔板
- Time Limit: 10000/5000 MS (Java/Others)
- Memory Limit: 65536/32768 K (Java/Others)
- Total Submission(s): 4318
- Accepted Submission(s): 1033
Problem Description
在魔方风靡全球之后不久,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
给你魔板的初始状态与目标状态,请给出由初态到目态变换数最少的变换步骤,若有多种变换方案则取字典序最小的那种。
Input
每组测试数据包括两行,分别代表魔板的初态与目态。
Output
对每组测试数据输出满足题意的变换步骤。
Sample Input
12345678
17245368
12345678
82754631
Sample Output
C
AC
Author
LL
Source
ACM暑期集训队练习赛(三)
Recommend
linle
题目大意
如题
解题思路
- 先考虑暴力,对于每个初态,按A,B,C的顺序BFS,到末态,输出。
- 不过,似乎有些问题。
- 问题1:如何表示状态?
- 问题2:多组数据每次都BFS的话,会T,咋办?
对于问题1,我们不难发现,不同状态其实对应了1-8的一个排列,很明显根据常识我们知道排列是有顺序的(逆序数逐渐增大) 那么我们可否根据排列的数组得到他对应全排列里的序号?其实这和康托展开就搭上关系了。
- 康拓展开:康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。
稍微详细点的介绍放在收获与反思里。
这样我们就解决了表示状态的问题。
那么对于问题2呢。我们会发现,魔板从初态到末态,重要的是每个板子相对位置的变化,而不是板子的数。换言之,我们可以做一个初态到'12345678'的映射,重新给板子标号, 再将末态各板子按映射关系对应新的标号,即末态按照映射对应一个新标号的末态。
初态 末态
75621483 -> 13846572
↓ 映射
12345678 -> 58763214
代码为
rep(i,0,len1){
hhash[raw1[i]-'0']=i+1;
}
rep(i,0,len1){
b[i]=hhash[raw2[i]-'0'];
}
保留板子相对移动的位置不变化即可,这样我们只要预处理一下'12345678'到各个排列的末态,然后对每组输入,做映射到'12345678',输出新末态的结果即可。
解题代码
1 |
|
收获与反思
- 本题综合应用了数论里的康托展开(用于找到状态数和排列之间的联系),hash到相同情况讨论,以及BFS,值得深入考虑
关于康托展开 https://www.cnblogs.com/linyujun/p/5205760.html 大部分是通过这篇博客以及其他资料学习的,感谢原作者!
公式为 \[ X = a_n \times (n-1)! + a_{n-1} \times (n-2)! + \cdots + a_2 \times 1! + a_1 \times 0! \]
其中\(a_n\)表示第i个元素在未出现的元素中排列第几(从0开始) ,也可以理解成\(a_n\)表示该位的逆序数。
康托展开得到的X,就是该排列在全排列中的顺序(从0开始)。
逆展开就是循环除以(n-1)!,商为第n位在未出现元素排列第几(从0开始)。模为下一位的被除数。
在详细的等开个数论专题(挖坑)。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!