ecjtuacm2022 C-n层妖塔

Description

链接:https://ac.nowcoder.com/acm/contest/44482/C
来源:牛客网

n层妖塔是一座有n层的妖塔。当然,这是废话。

最下面是第11层,最上面是第nn层,每一层都有一个守护者,第ii层的守护者的战力是a_ia  。当且仅当挑战者的战力严格大于守护者的战力时,才可以将其击败。挑战者鸡败第ii层的守护者后可以前往第i+1i+1层,当战胜第nn层的守护者后,视为挑战成功。

挑战一次守护者会耗费一点时间,并且挑战成功后会获得一点战力提升。如果挑战者无法击败该层守护者,挑战者可以选择花费一点时间来修炼,每次修炼后会获得一点战力提升。

但是守护者的战力并不是越高层越强大,并且挑战者也并不一定是从第11层开始挑战。

现在,有mm个挑战者,第ii个挑战者的战力为b_ib  ,其开始挑战的层数为s_is 

​请你计算出每一名挑战者挑战成功所需要花费的最短时间。

在这里插入图片描述

Demo1

input

5 2
1 3 3 7 5
2 1
1 2

output

8
9

说明

对于第一个战力为2从第一层开始的挑战者:
花费1点时间击败第一层,战力变为3。
由于无法击败第二层,所以花费1点时间修炼,战力变为4。花费1点时间击败第二层,战力变为5。
花费1点时间击败第三层,战力变为6。
由于无法击败第四层,花费2点时间修炼,战力变为8。花费1点时间击败第四层,战力变为9。
花费1点时间击败第五层,战力变为10。
共花费了8点时间。

Demo2

input

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

output

8
7
8
7
4

Analysis

萌新,看到这题直接暴力走了一遍常规思路,按照题意模拟了一遍如下:

n, m = list(map(int, input().split()))
a_arr = list(map(int, input().split()))
b_arr = []
for i in range(m):
    # [战力,开始层数]
    b_arr.append(list(map(int, input().split())))
    ori_power = b_arr[i][0]

    # npc: j层数, a_arr[j]战力
    for j in range(b_arr[i][1] - 1, len(a_arr)):
        if b_arr[i][0] > a_arr[j]:
            b_arr[i][0] += 1
        else:
            b_arr[i][0] += a_arr[j] - b_arr[i][0] + 1

    print(b_arr[i][0] - ori_power + 1)

结果嘿嘿,直接超时,复杂度n^2了,笨方法,方法2如下:

"""
假设当前需要从第 层开始挑战,考虑战力至少为多少时,才能恰好不受阻碍(指不需要中途修炼)的挑战成
功。假设该临界战力是 ,那么挑战者的战力如果大于等于 ,那么直接一路平推过去即可。如果战力小于 ,我
们不妨在挑战之前,先把战力修炼到 ,然后在出发挑战。否则,我们一定会在挑战某一层的时候需要修炼。而
我们只是将所有的中途修炼改为了提前修炼。
我们定义f[i]表示从第 层开始挑战,战力至少为多少,才能不受阻碍的挑战成功。显然我们需要提前预处理出来
这个f数组。其可以使用递推的方式进行求解。递推方程为f[i] = max(a[i] + 1, f[i+1] - 1)
时间复杂度O(m+n)
"""

n, m = map(int, input().split())
f = list(map(int, input().split()))
f.insert(0, 0)
f[n] += 1

for i in range(n - 1, 0, -1):
    f[i] = max(f[i] + 1, f[i+1] - 1)
print(f)
for i in range(m):
    b, s = list(map(int, input().split()))

    if b >= f[s]:
        print(n - s + 1)
    else:
        print(f[s] - b + n - s + 1)

方法二递推了一遍,快多了,复杂度O(m+n)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
题目描述: 给定一个m*n的稀疏矩阵,其中共有a个非零元素。请编写算法,实现以下功能: 1. 将稀疏矩阵转换为三元组表。 2. 将稀疏矩阵进行转置。 3. 将转置后的矩阵还原为原始矩阵。 解题思路: 1. 将稀疏矩阵转换为三元组表。 三元组表是一种常用的稀疏矩阵存储方式,它将矩阵中的每个非零元素存储为一个三元组(i, j, val),其中i和j分别表示该元素在矩阵中的行和列,val表示该元素的值。 对于给定的稀疏矩阵,我们可以遍历矩阵中的每个元素,将非零元素存储为一个三元组,最终得到三元组表。 2. 将稀疏矩阵进行转置。 对于一个m*n的矩阵,其转置矩阵为n*m的矩阵。对于稀疏矩阵,我们可以先将其转换为三元组表,然后将每个三元组的行和列交换,得到转置后的三元组表。最后将转置后的三元组表转换为稀疏矩阵即可。 3. 将转置后的矩阵还原为原始矩阵。 对于转置后的矩阵,我们可以先将其转换为三元组表,然后按照行和列的顺序重新构造矩阵。具体地,我们可以遍历三元组表中的每个元素,将其值存储到对应的行和列中。最终得到原始矩阵。 代码实现: 以下是Python代码实现: ```python # 将稀疏矩阵转换为三元组表 def to_triplet(matrix): m, n = len(matrix), len(matrix[0]) triplet = [] for i in range(m): for j in range(n): if matrix[i][j] != 0: triplet.append((i, j, matrix[i][j])) return triplet # 将稀疏矩阵进行转置 def transpose(matrix): triplet = to_triplet(matrix) trans_triplet = [(j, i, val) for i, j, val in triplet] trans_matrix = [[0] * len(matrix) for _ in range(len(matrix[0]))] for i, j, val in trans_triplet: trans_matrix[i][j] = val return trans_matrix # 将转置后的矩阵还原为原始矩阵 def restore(trans_matrix): trans_triplet = to_triplet(trans_matrix) matrix = [[0] * len(trans_matrix[0]) for _ in range(len(trans_matrix))] for i, j, val in trans_triplet: matrix[i][j] = val return matrix # 测试代码 matrix = [[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0], [0, 0, 0, 4]] print(to_triplet(matrix)) # [(0, 0, 1), (1, 1, 2), (2, 2, 3), (3, 3, 4)] print(transpose(matrix)) # [[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0], [0, 0, 0, 4]] print(restore(transpose(matrix))) # [[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0], [0, 0, 0, 4]] ``` 参考资料: [1] 《算法导论》 [2] https://www.cnblogs.com/ECJTUACM-873284962/p/7647949.html

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zeeland

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值