1 solutions
-
0
思路:搜索+剪枝
给定一个 的矩形,我们需要从中分割出若干个正方形,要求正方形个数最少,求该个数。
这道题初看很容易认为是用分治的做法,通过枚举分割长度将矩形分成两块,分别求两块最少能分割的正方形区域再相加,并不断递归求解。
先详细说明下错误的分治的做法:
假设当前矩形的长宽分别为 ,且有
- 枚举分割长度 ,从而得到两个大小的矩形 和
- 将两个矩形当成子问题,即求解两个矩形最少能分割出多少正方形,于是又回到第一步
- 直到到达边界条件 ,此时能分割一个正方形,返回
- 在每次子问题求解完毕后,取两个子问题和的最小值作为当前矩形的最小值
但实际上看下样例2就会发现这样的解法是错误的,其分割方法很不规则,而分治的方法得到的分割方法很规则(因为每次都是整齐的分割成两个矩形,而样例2的分割是不整齐的)。分治在样例2上求出来的答案一般来说是8而不是6(可以自己尝试一下)。
由于样例2分割的不规则性,在发现分治无效后,也难以想到其它有效的解法。于是尝试使用搜索+剪枝求解。
(这其实是一个NP问题,但是当我们在比赛时,我们既不了解该问题,也不能想到有效的解法,就只能尝试用搜索方法尽可能拿分)
搜索规则如下:
定义 表示该点是否已经被分割为了一个正方形
- 找到一个的点,即该点未被分割为正方形
- 尝试以该点为正方形第一个点(即左上角点)分割正方形,即枚举正方形长度,尝试分割一个固定边长的正方形
- 将分割的区域标记为,表示已经分割了正方形
- 重新回到第1步,直到无法找到未被标记的点
既然用了搜索,那肯定逃不掉的就是剪枝了,剪枝的方法有很多,这里提出几个主要的剪枝,有其它更优秀剪枝方法的可以自行添加:
- 记录当前已经找到的最小的答案,记为,在搜索过程中,如果当前统计的分割的正方形数(记为),有,说明继续找下去答案也不会更优了,可以直接回退
- 枚举分割正方形的边长时,从大往小枚举,这样能够尽早找到一个较小的答案,从而在后续搜索中减少搜索量
搜索的时间复杂度很难衡量,所以这里就不进行时间复杂度的计算了。
代码
C++
python
Java
Go
Js
- 1
Information
- ID
- 35
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 7
- Tags
- # Submissions
- 46
- Accepted
- 15
- Uploaded By