题解 | #合唱队#

合唱队

https://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4

import copy

N = int(input())
heights = list(map(int, input().split(" ")))

def dp_arr(in_list, num):
    lr = [[-1 for _ in range(num)] for _ in range(2)]
    least_slope = [-1 for _ in range(num)]
    for i in range(num):
        for j in range(i, num):
            if i == 0:
                if j == 0:
                    lr[1][j] = 0
                    least_slope[i] = 0
                elif in_list[j] <= in_list[lr[1][j - 1]]:
                    lr[1][j] = j
                else:
                    lr[1][j] = lr[1][j - 1]
            elif lr[1][j - 1] == -1:
                if lr[0][j - 1] == -1:
                    continue
                elif in_list[j] > in_list[lr[0][j - 1]]:
                    lr[1][j] = j
                    least_slope[i] = j
            else:
                if (
                    in_list[j] < in_list[lr[1][j - 1]]
                    and in_list[j] > in_list[lr[0][j - 1]]
                ):
                    lr[1][j] = j
                else:
                    lr[1][j] = lr[1][j - 1]
        if lr[1][-2] == -1 or lr[1][-1] == -1:
            break
        lr[0] = copy.deepcopy(lr[1])
        lr[1] = [-1 for _ in range(num)]
    return lr, least_slope

left2right, left_ls = dp_arr(heights, N)
del left2right
heights_rev = list(reversed(heights))
right2left, right_ls = dp_arr(heights_rev, N)
del right2left

while left_ls[-1] == -1:
    del left_ls[-1]
while right_ls[-1] == -1:
    del right_ls[-1]

left_idx = 0
right_idx = len(right_ls)-1
max_people = 0
i = N*1
for i in range(len(left_ls)):
    for j in range(len(right_ls)):
        if left_ls[i] == -1:
            break
        elif right_ls[j] == -1:
            continue
        elif left_ls[i] + right_ls[j] + 2 <= N:
            max_people = max(max_people, i + j + 2)
        else:
            continue

print(N - max_people)

从左往右扫一遍,目标是得到,当有i个元素的递增序列时,最右端索引最小的元素,即least_slope,其索引i表示几个元素构成的递增序列,元素值表示序列右边最小索引值

从右往左进行同样的过程(把heights reverse一下)

得到这两个slope后,穷举。即,如果left_ls的元素和right_ls元素之和+2不大于总元素个数的情况下(左右递增序列的最高值不对撞),总元素最大的情况(即,此时两个列表的索引相加)

为了减少时间,如果lr[1]的最右边只有一个非-1时退出

为了减少空间,只存两行lr——行存法

不是最优方法,却是第一次靠自己做出来的dp

全部评论

相关推荐

11-05 07:29
贵州大学 Java
点赞 评论 收藏
分享
11-15 17:19
湖南大学 Java
成果成果成果果:这是哪个公司的hr,这么离谱吗,我没见过用性别卡技术岗的,身边女性同学拿大厂offer的比比皆是
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务