1.7 光影切割问题
题意:给定n条直线,计算它们在某个水平区间内相交所划分的区域数。注:不存在三条直线相交于一点的情况。
解法一首先从划分的区域数目和交点的关系开始考虑,通过观察小样本的数据与归纳,发现区域数等于直线数N+交点数M+1。故可以根据直线数据,计算相交的情况,判定交点的区间位置,最终得到划分区域的个数。
解法二的逆序数的方法是个很好的解法,充分利用了问题的特性(若线的顺序交错,则必然是相交的),并将其与简单数学模型对应起来,避免了交点坐标计算与区间判定。
由于问题并没有要求给出具体的区域信息,所以在处理问题的时候,若能找到适合的逻辑关系,就可以避免具体的数值计算。
1.8 小飞的电梯调度算法
题意:一栋楼有N层,给定去每层楼的人数,电梯只能停在某个楼层。问电梯停在哪一楼层,所有人需要爬楼梯的层数最少?
问题非常简单,所以给定一个层,能够很快统计出所有人需要爬楼梯的层数,枚举所有层,则最小值就找到了。这就是解法一的方法,平方复杂度。
解法二实际上是一种增量法,考虑的不是总量,而是变化量,这样每次与相邻的方案比较,最终也能找出最优解。
解法一比解法二复杂度高这么多,主要还是因为有太多的重复计算(重复的是信息,不是数据),相邻的两个楼层的计算,在计算内容上差别并不大,其中的公共部分,完全可以利用已有的信息。
from xmlrpclib import MAXINT def f1(person, N): nTargetFloor = -1; nMinFloor = MAXINT for i in range(N): nFloor = 0 for j in range(i): nFloor += person[j] * (i - j) for j in range(i, N): nFloor += person[j] * (j - i) if nMinFloor > nFloor: nMinFloor = nFloor nTargetFloor = i; return nTargetFloor, nMinFloor def f2(person, N): nTargetFloor = 0 nMinFloor = 0 N1, N2, N3 = 0, person[0], 0 for i in range(1, N): N3 += person[i] nMinFloor += person[i] * i; for i in range(1, N): if N1 + N2 < N3: nTargetFloor = i nMinFloor += N1 + N2 - N3; N1 += N2; N2 = person[i] N3 -= person[i] else: break return nTargetFloor, nMinFloor if __name__ == "__main__": person = [1, 1, 2, 3] N = len(person) print f1(person, N) print f2(person, N)