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)
posted on 2012-10-19 11:36  罗辑  阅读(189)  评论(0编辑  收藏  举报