目录
1.问题描述
如图所示,有一块长方形土地,假设长168,宽64,现在要将这块地均匀地分成方块,且分出的方块要尽可能大。
2.问题分析
使用分而治之的思想解决问题,包括两个步骤:
(1)找到基线条件,这种条件必须尽可能简单
(2)把问题不断分解,直到符合基线条件
2.1基线条件
对于把长方形分成正方形,且分出的正方形要尽可能大,需要以当前长方形的短边作为正方形的边长,不断往下划分。那划分到什么时候停止呢?我一开始想的是一直划分到剩下的长方形长和宽相等时停止,但这个条件并不是最大的基线条件。书中给出的基线条件是当长方形长边是短边的整数倍。仔细分析,可以发现,长宽相等是整数倍条件的一个特例,太过于简单,这样会增加递归的深度,导致堆栈占用过多。
2.2问题分解
在每一次划分的过程中,应该是对长边进行切割,分为短边的整数倍部分和剩余部分(有时候长边是短边的n倍,可以一次划分出n个正方形,如果此时一次只划分一个方块,会增加迭代次数)
3.Python代码实现
python代码如下所示
import math
from PIL import Image
from PIL import ImageDraw
square_width=[]
def division(length,width):
remainder=length%width
if remainder==0:
multiple = int(math.floor(length / width))
for i in range(multiple):
square_width.append(width)
else:
multiple=int(math.floor(length/width))
for i in range(multiple):
square_width.append(width)
remain=length-multiple*width
length=width
width=remain
division(length,width)
if __name__=='__main__':
length=168
width=64
division(length,width)
print(u'划分的正方形边长:',square_width)
im=Image.new('RGB',(length,width),'white')
draw=ImageDraw.Draw(im)
draw.line([(0,0),(length-1,0),(0,width-1),(length-1,width-1)],fill='black')
#绘制划分后的土地
x1=0
x2=square_width[0]
y1=0
y2=square_width[0]
draw.rectangle((x1,y1,x2,y2),fill='blue',outline='black')
x1=square_width[0]
x2=square_width[0]*2
draw.rectangle((x1, y1, x2,y2), fill='blue',outline='black')
x1=x2
x2=square_width[2]+2*square_width[1]
y2=square_width[2]
draw.rectangle((x1, y1, x2, y2), fill='orange',outline='black')
y1=y2
y2=y1+square_width[3]
x2=x1+square_width[3]
draw.rectangle((x1, y1, x2, y2), fill='green',outline='black')
x1=x2
x2=x1+square_width[4]
y2=y1+square_width[4]
draw.rectangle((x1, y1, x2, y2), fill='red',outline='black')
y1+=square_width[4]
x2=x1+square_width[5]
y2=y1+square_width[5]
draw.rectangle((x1, y1, x2, y2), fill='purple',outline='black')
x1=x2
x2=x1+square_width[6]
draw.rectangle((x1, y1, x2, y2), fill='purple',outline='black')
im.save('../Algorithm_diagram/land_division.png')
im.show()
如图所示,使用python实现了土地的划分
4.总结
(1)分而治之实际上是一种递归解决问题的方式,因此在选择基线条件时,简单的同时尽可能减少递归深度,如果深度过深,会占用大量的栈资源。
(2)分解问题时,每次递归应完成尽可能多的任务,不要作重复工作内容的递归。