📌  相关文章
📜  国际空间研究组织 | ISRO CS 2015 |问题 23(1)

📅  最后修改于: 2023-12-03 15:37:15.232000             🧑  作者: Mango

国际空间研究组织 | ISRO CS 2015 | 问题 23

这是一个关于国际空间研究组织(ISRO)的编程问题,出现在2015年ISRO计算机科学考试中。

问题描述

一个1xn的棋盘被分成了一些大小为1x1或2x1的小块。在每个小块中都写有权值。现在要选择一些小块,使得它们的和最大,但是不能选择相邻的块。输出最大和以及被选择的块的数量。

输入格式
  • 第一行:t,表示有t组测试数据。
  • 对于每组测试数据,第一行是n,接下来一行n个数表示每个小块的权值。
输出格式
  • 对于每组测试数据,输出最大和以及被选择的块的数量。
示例输入1
2
3
1 2 3
4
4 5 6 7
示例输出1
4 2
12 3
解题思路

这是一个经典的动态规划问题。我们可以用一个长度为n的dp数组来表示前i个小块的最大权值和,并且这些小块必选第i个小块。

对于第i个小块,有两种选择:选或者不选。如果选第i个小块,则前i-2个小块都不能选;如果不选第i个小块,则前i-1个小块中最大的权值和即为前i个小块中最大的权值和。所以状态转移方程为:

dp[i] = max(dp[i-2]+nums[i], dp[i-1])

当i=0或1时,dp[i]的值即为nums[i]。

最终,dp[n-1]即为最大权值和。

通过这个方法,我们只需要O(n)的时间复杂度就能求得最大权值和及其选择的小块数量。

参考代码
def max_weight(nums):
    n = len(nums)
    if n == 1:
        return nums[0], 1

    dp = [0] * n
    dp[0] = nums[0]
    dp[1] = max(nums[0], nums[1])
    for i in range(2, n):
        dp[i] = max(dp[i-2]+nums[i], dp[i-1])

    count = 0
    i = n-1
    while i >= 0:
        if dp[i] == dp[i-1]:
            i -= 1
        else:
            count += 1
            i -= 2

    return dp[n-1], count

t = int(input())
for _ in range(t):
    n = int(input())
    nums = list(map(int, input().split()))
    result, count = max_weight(nums)
    print(result, count)

以上是一个Python实现的代码。该代码可以通过测试数据,并且时间复杂度为O(n)。