首页 > 试题广场 >

合唱队形

[编程题]合唱队形
  • 热度指数:14253 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK, 则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入描述:
输入的第一行是一个整数N(2 <= N <= 100),表示同学的总数。
第一行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。


输出描述:
可能包括多组测试数据,对于每组数据,
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
示例1

输入

8
186 186 150 200 160 130 197 220

输出

4
计算两次最长递增子序列,然后 n - max1 - max2 + 1找数字最小值
import sys
line = sys.stdin.readline().strip()
n = int(line)
line = sys.stdin.readline().strip()
h = list(map(int, line.split()))


def lengthOfLIS(nums): 
    m = len(nums)
    if(m == 0):
        return 0
    dp = [0 for i in range(m)]
    maxx = 1    
    for i in range(m):
        maxn = 1
        for j in range(i):
            if (nums[i] > nums[j]):
                maxn = max(maxn, dp[j] + 1)                
        dp[i] = maxn
        maxx = max(maxn,maxx)    
    return maxx

minn = n
for i in range(1,n):
    t = lengthOfLIS(h[:i])
    q = h[i-1:]
    q = q[::-1]
    s = lengthOfLIS(q)
    minn = min(n - t - s + 1, minn)

print(minn)


编辑于 2019-08-21 22:24:18 回复(0)

两个动态规划,找出左到右递增时最长子序列长度,右到左递增时最长子序列长度。
然后相同下标相加长度相加-1就得到题目要求的队形长度。就可以得到去除的人数

#找出一个方向上的递增子序列长度
def findAscSubString(peopleNum, heightList):
    ascSubNum = [1] * peopleNum
    for i in range(peopleNum):
        if heightList[i] != min(heightList[:i + 1]):
            for j in range(i):
                if heightList[i] > heightList[j]:
                    if ascSubNum[i] < ascSubNum[j] + 1:
                        ascSubNum[i] = ascSubNum[j] + 1
    return ascSubNum

#得到去除的队员人数
def findRemovePeople(peopleNum, heightList):
    leftPeople = findAscSubString(peopleNum, heightList)          #左到右递增
    rightPeople = findAscSubString(peopleNum, heightList[::-1])   #右到左递增
    rightPeople.reverse()                                 #反转得到下标对应
    stayPeople = 0
    for i in range(peopleNum):
        if stayPeople < leftPeople[i] + rightPeople[i]:
            stayPeople = leftPeople[i] + rightPeople[i]
    return peopleNum - stayPeople + 1


while True:
    try:
        peopleNum = int(input())
        heightList = list(map(int, input().split()))
        print(findRemovePeople(peopleNum, heightList))
    except Exception:
        break

编辑于 2018-10-01 17:44:44 回复(0)