PythonACM测试题之庆祝建国七十周年阅兵

题目信息

Description:

细心的木斤发现:某一方阵走在第一列的n个军人,从左到右是按照各自的身高升序排列的,但体重上从左到右出现了乱序,木斤分别给这n个军人按照体重设定了不同的权值(从左到右第i个人的权值设为a[i])。他想知道:从左往右最多会有多少相邻的人其权值是严格升序排列的呢?(严格升序排列:a[i+1]>a[i])

输入输出及测试案例

Input:
测试数据有多组,每组两行,输入直到文件末尾。每组输入的第一行是一个整数n,表示这一方阵走在第一列的军人数。接下来一行是n个整数,表示从左到右每个军人的权值。
Output:
对于每组输入,输出一个整数,表示满足条件的最大人数,每个结果占一行。
Sample Input:

7
5 1 1 2 3 4 1
5
1 2 6 1 2

Sample Output:

4
3

个人参考答案

解题思路

这道题可以用动态规划来解决。定义 dpi 表示以第 i 个人为结尾的最长严格升序排列的长度,则我们需要求的就是 dp 数组中的最大值。
对于每个 i,我们遍历其之前的所有人 j,如果 a j < a i ,则 j 可以加入到以i 结尾的最长严格升序排列中,此时 dpi 取 dpj +1 的最大值。最终,dp 数组中的最大值就是我们所求的答案。

代码实现

#将每组测试数据的结果保存在一个列表中
ans = []

while True:
    try:
        # 输入n和权值数组
        n = int(input())
        a = list(map(int, input().split()))
        # 初始化dp和res
        dp = [1] * n
        res = 1
        # 转移dp数组,并更新res
        for i in range(1, n):
            for j in range(i):
                if a[j] < a[i]:
                    dp[i] = max(dp[i], dp[j] + 1)
            res = max(res, dp[i])
        # 将本组测试数据的结果加入列表
        ans.append(res)
    except:
        break

# 输出所有测试数据的结果
for res in ans:
    print(res)

与此同时,我们可以使用二分查找优化算法,代码如下:

while True:
    try:
        # 输入n和权值数组
        n = int(input())
        a = list(map(int, input().split()))
        # 初始化tail和ans
        tail = [a[0]]
        ans = 1
        # 更新tail数组,并更新ans
        for i in range(1, n):
            if a[i] > tail[-1]:
                tail.append(a[i])
            else:
                # 在tail数组中查找第一个大于等于a[i]的数的位置pos,用a[i]替换tail[pos]
                l, r = 0, len(tail) - 1
                while l < r:
                    mid = (l + r) // 2
                    if tail[mid] >= a[i]:
                        r = mid
                    else:
                        l = mid + 1
                tail[r] = a[i]
            ans = len(tail)
        # 输出结果
        print(ans)
    except:
        break

利用二分查找的这种方法利用 tail 数组保存当前已经能够形成的最长严格升序排列。在遍历第 i 个人时,如果 ai 大于 tail 数组中的最后一个元素,则 ai 可以加入到 tail 数组末尾;否则,在 tail 数组中二分查找第一个大于等于 ai 的数的位置 pos,然后用 ai 替换掉 tail[pos]。最终,tail 数组的长度就是我们所求的答案。

题目来源: http://acm.zjgsu.edu.cn/problems/4037/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值