题解 | 收集金币

收集金币

https://www.nowcoder.com/practice/bde230df252c4b41a059c9b06fcf65b6

import sys
# 定义极大值
INF = 0x3f3f3f3f

def kkk():
    # 读取输入
    input_data = sys.stdin.read().split()
    ptr = 0
    
    # 读取行列数(n行m列)
    n = int(input_data[ptr])
    m = int(input_data[ptr+1])
    ptr += 2
    
    # 初始化网格(1-based索引,方便对标C++)
    # a[i][j] 对应原C++的a[N][N],存储原始收益
    a = [[0]*(m+2) for _ in range(n+2)]  # 多开1列/行避免越界
    for i in range(1, n+1):
        for j in range(1, m+1):
            a[i][j] = int(input_data[ptr])
            ptr += 1
    
    # 初始化dp和cost数组(1-based)
    # dp[i][j]:从(1,1)走到(i,j)的最大收益,初始为-INF(不可达)
    dp = [[-INF]*(m+2) for _ in range(n+2)]
    # cost[i][j]:陷阱触发步数,初始为INF(无陷阱)
    cost = [[INF]*(m+2) for _ in range(n+2)]
    
    # 读取陷阱数量和陷阱信息
    t = int(input_data[ptr])
    ptr += 1
    for _ in range(t):
        x = int(input_data[ptr])
        y = int(input_data[ptr+1])
        v = int(input_data[ptr+2])
        ptr += 3
        cost[x][y] = v  # 记录陷阱触发步数
    
    # 处理陷阱:触发则将该位置收益设为-INF(不可达)
    for i in range(1, n+1):
        for j in range(1, m+1):
            step = i + j - 2  # 1-based步数计算
            if cost[i][j] <= step:
                a[i][j] = -INF
    
    # 边界初始化
    dp[1][0] = 0  # 第一行的左边界,方便j=1时取dp[i][j-1]
    dp[0][1] = 0  # 第一列的上边界,方便i=1时取dp[i-1][j]
    
    # 动态规划状态转移(1-based遍历)
    for i in range(1, n+1):
        for j in range(1, m+1):
            # 取上方/左方的最大合法收益
            max_prev = max(dp[i-1][j], dp[i][j-1])
            # 仅当前驱路径合法时更新(避免-INF叠加导致溢出)
            if max_prev != -INF:
                dp[i][j] = max_prev + a[i][j]
    
    # 遍历所有位置取最大收益
    res = -1  
    for i in range(1, n+1):
        for j in range(1, m+1):
            if dp[i][j] > res:
                res = dp[i][j]
    
    # 输出结果(若所有路径都不可达,仍输出-1)
    print(res)

if __name__ == "__main__":
    kkk()

全部评论

相关推荐

12-03 03:32
安徽大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务