概述
本文承接上文《求n个元素的全排序(从分治思想超详细解析)》),将再用一个详细的案例来带我们更深入的理解分治思想在解决实际问题中的体现。
同时,在后文我会把将前文的知识整合起来写成《算法分析与设计实验》的实验报告2—递归与分治策略应用基础,分享给大家。同为大学狗的可以借鉴一下👴的微薄之作
L型骨牌覆盖问题
1.问题说明
在一个 2^k 2^k 方格组成的棋盘中,若恰有一个方格与其他方格不同,称该方格为特殊方格,且称该棋盘为特殊棋盘(Defective Chessboard)。下图的特殊棋盘是当k=2 时16个特殊棋盘中的一个,在棋盘覆盖问题中,要求用图示所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何俩个L型骨牌方格不得重叠。在任何一个2k2k 的覆盖棋盘中,用到的L型骨牌个数为(4^k-1)/3。
2.算法分析
同样,我们可以把这个问题利用分治思想拆分成一个一个的小问题。
分治的技巧在于如何划分棋盘,使划分后的子棋盘大小相同,并且每一个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。
当k>0时,将2k 2k的棋盘划分为4个2(k-1)2(k-1)子棋盘,我们可以推断出原棋盘只有一个特殊方格,则其余三个子棋盘中没有特殊方格。
由于我们是L型骨牌,所以这三个没有特殊方格的子棋盘的结合处我们可以正好用L型骨牌覆盖,一旦覆盖,他们在各自的子棋盘中又会变成棋盘覆盖问题,不过规模变小了,之后我们就可以逐步递归求解,直至将棋盘分割为1*1 的子棋盘。
这里解释一下结合处,比如左上棋盘的结合处就是右下角,右上棋盘的结合处就是左下角,反正就是对立的
由此,我们得出核心的算法思路:
- 把大棋盘先分成4个小棋盘
- 依次判断每个小棋盘里有没有特殊方格,如果没有,将结合处用L型骨牌覆盖上,注意这时候一旦覆盖说明在这个小棋盘中有了一个特殊方格(就是刚刚被覆盖掉的那一个格子),我们需要递归。如果有,我们直接递归寻解。
- 一旦棋盘分割为1*1 的子棋盘表明递归终止。
3.代码实现
1 | //L型骨牌从1开始连续编号 |
测试代码
1 | public static void main(String[] args) { |
测试结果
1 | 4 4 5 5 9 9 10 10 25 25 26 26 30 30 31 31 |
结语
没想到吧,👴没分享实验报告,主要是我想了想,这两篇博文基本都涵盖了实验报告的全部内容,就不套娃了,基本上想白嫖一个实验报告的直接看一遍大概内容复制粘贴就完事了。
还有一个主要原因是👴也想复制粘贴去完成实验报告,直接复制markdown文字到doc上还得改字体大小,👴嫌麻烦,就委屈你们了。
一人之下3的片头曲真不错,爱了爱了。