在一个2 k ∗2 k (k为正整数,k<=10,length=2 k )个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格(其坐标为a,b,分别代表行坐标号和列坐标号),以及有四种l型骨牌(如下图)。求用若干块这种l型骨牌实现除该特殊点棋盘的全覆盖。(本题要求采用分治算法做)
时间: 2023-05-31 17:18:45 浏览: 459
### 回答1:
题目描述:
在一个 $2^k \times 2^k$ 的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格(其坐标为 $a,b$,分别代表行坐标号和列坐标号),以及有四种 L 型骨牌(如下图)。求用若干块这种 L 型骨牌实现除该特殊点棋盘的全覆盖。(本题要求采用分治算法做)
解题思路:
本题可以采用分治算法来解决。具体思路如下:
1.将棋盘分成四个等分的子棋盘,分别为左上、右上、左下、右下。
2.判断特殊方格在哪个子棋盘中,分别对该子棋盘进行递归处理。
3.对于每个子棋盘,先判断是否只有一个方格,如果是,则直接用一块 L 型骨牌覆盖该方格即可。
4.如果不止一个方格,则先用一块 L 型骨牌覆盖特殊方格所在的位置,然后将该子棋盘的其他方格分成三个部分:上部、下部和右侧。对于上部和下部,可以用两块 L 型骨牌覆盖;对于右侧,可以用一块 L 型骨牌覆盖。然后对于左上、右上、左下、右下四个子棋盘分别进行递归处理。
5.递归结束条件为棋盘只有一个方格。
代码实现:
下面是 Python 代码实现:
### 回答2:
题目要求用l型骨牌实现除了特殊点以外的全覆盖,我们可以先思考一下用l型骨牌是否可以实现全覆盖。显然,由于l型骨牌本身就是由三个方块组成的,而棋盘中的方块数也是三的倍数,因此如果l型骨牌能够实现全覆盖,那么必定是刚好用了全部的l型骨牌。因此,我们可以设想一下如何用尽可能少的l型骨牌实现全覆盖。
我们可以将棋盘分成四个方块,每个方块的大小都是2^(k-1)*2^(k-1),并且每个方块都包含了一个特殊点。因此,我们只需要分别将这四个方块用l型骨牌覆盖即可。为了方便,我们可以将这四个方块按照从左到右、从上到下的顺序分别命名为A、B、C、D。
接下来考虑如何用l型骨牌实现对A区域的全覆盖。如果我们能够覆盖A区域,那么B、C、D区域的覆盖方式也就随之而来了。显然,特殊点a,b只会出现在A或者C区域,因此我们只需要考虑A、C区域的情况即可。考虑将A区域分成四等份,如下图所示:
```
+-----+-----+
| C_1 | D_1 |
+-----+-----+
| B_1 | A_1 |
+-----+-----+
```
这时候我们可以发现,如果能够用l型骨牌覆盖A_1、B_1、C_1三个子区域,那么D_1区域也一定会被覆盖。这是因为D_1区域只能通过向上或者向左移动l型骨牌来覆盖,而移动骨牌的同时会产生新的空缺,而这个新的空缺不可能被覆盖。因此,只要A_1、B_1、C_1三个子区域中的任意一个不能被覆盖,那么整个A区域就不能被覆盖。
接下来考虑如何用l型骨牌覆盖A_1、B_1、C_1三个子区域。我们可以发现,按照下图所示的方式将A_1子区域再次分成四个子区域:
```
+-----+-----+
| C_2 | D_2 |
+-----+-----+
| B_2 | A_2 |
+-----+-----+
+-----+-----+
| C_3 | D_3 |
+-----+-----+
| B_3 | A_3 |
+-----+-----+
+-----+-----+
| C_4 | D_4 |
+-----+-----+
| B_4 | A_4 |
+-----+-----+
```
这时候你也许会想到采用递归的方式解决问题,也就是先覆盖A_4、B_4、C_4三个子区域,然后再依次覆盖A_3、B_3、C_3、A_2、B_2、C_2的子区域,直到最后覆盖完整个A_1子区域。这样做的复杂度比较好计算,每次递归都将区域分成四个子区域,并且每个子区域的大小是原来的1/4,因此总的复杂度是O(4^k)。
但是,事实上我们可以采用更巧妙的方法来实现全覆盖。具体地,我们考虑将A_1、B_1、C_1三个子区域中的一个(假设是B_1区域)分成两部分,如下图所示:
```
+-----+-----+
| C_1 | D_1 |
+-----+-----+
| B_2 | |
+-----+-----+
| B_1'|
+-----+
```
这时候,我们可以先用l型骨牌覆盖A_1、C_1、D_1三个子区域(具体方式不再赘述),然后再覆盖B_2、B_1'两个子区域。由于B_1、B_2、B_1'三个子区域的大小之和等于原来的B_1子区域的大小,因此我们可以采用递归的方式继续解决局部问题,直到每个子区域的大小都变成1*1为止。这样做的复杂度比较难计算,但是实际上非常优秀,实际运行速度很快。
总结一下,我们可以采用如下算法实现全覆盖:
1. 将棋盘按照左上、右上、左下、右下的顺序分成四个方块,分别用l型骨牌覆盖。
2. 要实现对左上方块的全覆盖,将左上块按照左上、右上、左下、右下的顺序分成四个子区域,将其中一块(比如左下)再次按照同样的方式分成四个子区域,然后依次用l型骨牌覆盖即可。
3. 递归地重复步骤2,直到覆盖完整张棋盘。
计算复杂度时,可以发现步骤1的复杂度是O(1),步骤2的复杂度是O(k^2),步骤3的复杂度是O(k^2logk),因此总的复杂度是O(k^2logk)。这样做的时间效率非常高,能够在k<=10的范围内迅速完成计算。
### 回答3:
首先,我们可以将这个棋盘划分成四个大小相等的子棋盘。因为每个L型骨牌都覆盖三个方格,而这个棋盘中除了特殊方格外,每个方格都需要被覆盖。因此,我们可以预先将特殊方格所在的子棋盘确定下来,然后分别对其它三个子棋盘进行求解。
接下来,我们要考虑在一个子棋盘中,如何用L型骨牌来实现覆盖。因为这个棋盘的大小是2^k * 2^k,所以我们可以将子棋盘划分成四个大小为2^(k-1) * 2^(k-1)的子棋盘。这个棋盘上的特殊方格所在的子棋盘将会是其中一个大小为2^(k-1) * 2^(k-1)的子棋盘。因为该子棋盘的大小仍然是2的幂次方,所以我们可以采用递归的方式对其进行求解。
在一个大小为2^m * 2^m(m<=k)的棋盘中,我们可以首先将其中的一个L型骨牌放在该棋盘的最中心。这个骨牌会覆盖中心的三个方格。然后,我们将该棋盘分成四个大小相等的子棋盘。接下来,我们在这四个子棋盘中,选择其中三个子棋盘来放置剩下的三个L型骨牌,而第四个子棋盘则可以通过递归再次进行求解。那么,到底应该选择哪三个子棋盘来放置这三个骨牌呢?
我们可以将这个问题转化为一个覆盖问题。也就是说,对于一个大小为2^m * 2^m的棋盘,我们假设它还需要被覆盖的方格集合为S。那么,我们可以首先将这个棋盘的最中心的三个方格从S中去除。接下来,我们可以将这个棋盘划分成四个大小相等的子棋盘A、B、C、D。然后,我们假设S被划分成了S_A,S_B,S_C,S_D四个子集。我们接下来需要考虑如何分别在A、B、C三个子棋盘中放置三个L型骨牌,使得它们可以覆盖掉子集S_A、S_B、S_C。那么,我们一个一个进行判断:
1. 这三个骨牌放在A、B、C中,然后递归求解D子棋盘
2. 这三个骨牌放在B、C、D中,然后递归求解A子棋盘
3. 这三个骨牌放在C、D、A中,然后递归求解B子棋盘
4. 这三个骨牌放在D、A、B中,然后递归求解C子棋盘
如果在任意一个子棋盘中,我们无法放置其中一个骨牌来覆盖该子集,那么就说明这个问题无解。否则,我们就可以分别在三个子棋盘中放置对应的骨牌,然后递归求解剩下的子棋盘。对于这个子棋盘,我们可以将它的特殊方格所在的子集再次递归求解,直到棋盘大小为1时结束。
总结起来,我们可以采用分治算法来求解这个问题。首先,我们找到棋盘中特殊方格所在的子棋盘,然后对其它三个子棋盘分别求解。对于一个子棋盘,我们可以递归地将它分成四个大小相等的子棋盘,然后依次尝试在三个子棋盘中放置L型骨牌,然后递归地求解剩下的子棋盘。如果最后发现该问题无解,则递归返回上一级。通过这个算法,我们可以在O(N^2)的时间复杂度内求解该问题。