topcoder: YetAnotherRobotSimulation

又一次暴力求解被羞辱,这个题感觉一定可以for循环代替递归,然而经验值不足(智商感人的委婉说法😢)没能在放弃之前想出来,于是再次拿来主义:

class YetAnotherRobotSimulation:
    def getMaximumProbability(self,L,x,y):
        px = tuple(x)
        py = tuple(y)
        tl = len(px)
        '''
        tp = []
        for i in range(0, tl):
            tp.append((px[i],py[i]))
        '''

        tp = {}
        for i in range(0, tl):
            tp[(px[i],py[i])] = True

        c = []
        # 一张屌炸天的排列组合速查表;生成它需要一点数学推导:
        # C(4,2) = C(3,1) + C(3,2)
        # 这里隐含了DP思想,知道了C(3,1)和C(3,2)这两种组合数,
        # 那么现在新加入一个元素,在4个元素里面挑出2个,无非是:
        # 要么用新的元素和原来所有1个元素的组合组成新的2元组,
        # 要么不选这个新的,直接用原来3个里面已有的2元组
        for i in range(0, 51):
            c.append([])
            for j in range(0, i+1):
                if j == 0:
                    c[i].append(1)
                else:
                    if j > i-1:
                        c[i].append(c[i-1][j-1])
                    else:
                        c[i].append(c[i-1][j-1]+c[i-1][j])

        m = 0
        u = r = l = d = 0
        # 只要按顺序列举出所有的指令seq组合即可,
        # 指令之间的排序根本不影响最终结果
        for u in range(0, L+1):
            for r in range(0, L-u+1):
                for l in range(0, L-u-r+1):
                    d = L-u-r-l
                    s = 0
                    pu = pr = pl = pd = 0
                    # 由于指令顺序不重要,
                    # 那么只要枚举出每种指令可能生效的次数即可
                    for pu in range(0,u+1):
                        for pr in range(0,r+1):
                            for pl in range(0,l+1):
                                for pd in range(0,d+1):
                                    # 这是一个小优化,事先准备好目标集合字典:m
                                    # 比在运行中不断用in来判断要快很多(1/4)
                                    #if (pr-pl, pu-pd) in tp:
                                    if tp.get((pr-pl, pu-pd), False):
                                        # 虽然生效指令的个数决定了最终到达的位置
                                        # 但是我们还是需要知道有多少种组合方式
                                        # 因为要算概率,需要知道当前指令序列能有
                                        # 多少种方式到达这里,所有能够到达目标
                                        # 集合的方式除以某个指令序列可能的所有
                                        # 生效形式(1<<L)就是它的到达目标概率
                                        s += c[u][pu]*c[r][pr]*c[l][pl]*c[d][pd]
                                        m = max(s, m)

        return float(m)/(1<<L)

 

Leave a Reply

Your email address will not be published. Required fields are marked *