用Python做50道ACM之《Number Trapezium》

15.Number Trapezium

http://acm.fzu.edu.cn/problem.php?pid=1020

难点在于判定路径重叠

思路:采用动态规划算法,自底向上进行运算。每次运算结果保存当前运算行的当前运算节点的左最大子路径和右最大子路径。任意两个相邻节点,对于它们的交叉路径(即左节点的右路径和右节点的左路径),判断二者是否有路径重叠,若是则保存两节点中较大节点的右(若大的为左节点)/左(若大的为右节点)子路径,删除另一个。

import sys

def max_sum(trapezium,n,m,k):
    path={} # 保存每个节点左右两个最大和路径
    max_line=n
    while n>1:
        n-=1
        length=len(trapezium[n-1]) # 从倒数第二行开始
        for i in range(0,length):
            present=trapezium[n-1][i] # 当前节点的值
            l_down=trapezium[n][i]
            r_down=trapezium[n][i+1]
            if n==max_line-1: #倒数第二行的长度为第一行的长度加上n-2
                path[str([n-1,i])]={
                    'lmp':[present,l_down],
                    'rmp':[present,r_down]
                }
            else:
                lmp=[present]
                rmp=[present]
                if sum(path[str([n,i])]['lmp'])==max(sum(path[str([n,i])]['lmp']),sum(path[str([n,i])]['rmp'])):
                    lmp.extend(path[str([n,i])]['lmp'])
                else:
                    lmp.extend(path[str([n,i])]['rmp'])
                if sum(path[str([n,i+1])]['lmp'])==max(sum(path[str([n,i+1])]['lmp']),sum(path[str([n,i+1])]['rmp'])):
                    rmp.extend(path[str([n,i+1])]['lmp'])
                else:
                    rmp.extend(path[str([n,i+1])]['rmp'])
                path[str([n-1,i])]={
                    'lmp':lmp,
                    'rmp':rmp
                }
            if i>0:# 从当前行的第二个节点开始判断路径是否重叠
                # 路径重叠的情况只会发生在交叉路径上
                p1=path[str([n-1,i-1])]['rmp']
                p2=path[str([n-1,i])]['lmp']
                if p1[1:]==p2[1:]:
                    if sum(p1)<sum(p2):
                        path[str([n-1,i-1])]['rmp']=[-9999]
                    else:
                        path[str([n-1,i])]['lmp']=[-9999]
                if path[str([n-1,i-1])]['rmp']==[-9999] and path[str([n-1,i-1])]['lmp']==[-9999]:
                    path[str([n-1,i-1])]['rmp']=path[str([n-1,i-1])]['lmp']=[trapezium[n-1][i-1]]
    sums=[] # 保留从第一行开始到最后一行的所有存在路径的各自的和
    for i in range(0,m):
        lmp=path[str([0,i])]['lmp']
        rmp=path[str([0,i])]['rmp']
        if len(lmp)==max_line:
            sums.append(sum(lmp))
        if len(rmp)==max_line:
            sums.append(sum(rmp))
    sums.sort()
    print(sum(sums[-k:]))

line_left=0
while True:
    read_in=sys.stdin.readline()
    if not read_in:
        break
    if line_left==0:
        N,M,K=tuple([int(x) for x in read_in.rstrip().split(' ')])
        line_left=N
        trapezium=[]
    else:
        trapezium.append([int(x) for x in read_in.rstrip().split('')])
        line_left-=1
        if line_left==0:
            max_sum(trapezium,N,M,K)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值