问题描述
小M最近在玩一款叫做"狼人拯救者”的游戏。在游戏中,玩家可以通过消耗金币来购买能力,这些能力会增加攻击力,但也会影响攻击速度。小M是一个以攻击力为优先的玩家,但他必须保证自己的攻击速度不能低于0,因为攻击速度为负时将无法攻击。现在小M面对商店中的N种能力,他拥有G枚金币和S点初始攻击速度。他想知道,在保持攻击速度大于等于0的前提下,他最多可以获得多少攻击力。 商店中每种能力用三元组表示为 array[i]=[c,s,d],其中: c表示购买该能力需要的金币数; 可以为正数、零或负数;s 表示该能力对攻击速度的影响, d 表示该能力对攻击力的增加值!
测试样例
样例1: 输入:n=6,g=100,s=100 ,array =[[71,-51,150],[40,50,100],[40,50,100],[30,30,70],[30,30,70],[30,30,70]]输出:240 样例2: 输入:n=6,g=100,s=100 ,array =[[71,-51,150],[40,-50,100],[40,-58,108],[30,-30,70],[30,-30,70],[30,-38,70]]输出:210 样例3: 输入:n=5,g=58,s=50 ,array =[[25,-25,100],[25,-25,50],[20,8,60],[15,-15,40],[10,-5,30]]输出:170
解答
有限制条件的背包问题,注意i和j代表的意义,所以最后不一定会把所有金币画完才是最好的答案。
代码
def solution(n, g, s, array):
# 初始化dp数组,dp[i][j]表示在前i种能力中,花费j金币时能够获得的最大攻击力
dp = [[[s, 0] for _ in range(g + 1)] for _ in range(n + 1)]
# 遍历每种能力
for i in range(1, n + 1):
c, speed_change, d = array[i - 1]
# 遍历金币数
for j in range(1, g + 1):
# 不选择当前能力,不用花钱
dp[i][j] = dp[i - 1][j]
if j < c:
continue
tmp_s, tmp_d = dp[i-1][j-c][0] + speed_change, dp[i-1][j-c][1] + d
# 选择当前能力,但需要保证攻击速度大于等于0
if tmp_s >= 0:
if tmp_d > dp[i][j][1]:
dp[i][j] = [tmp_s, tmp_d]
elif tmp_d == dp[i][j][1]:
dp[i][j] = [max(tmp_s, dp[i][j][0]), tmp_d]
else:
dp[i][j] = [dp[i][j][0], dp[i][j][1]]
# print(dp)
# 返回最大攻击力,可以不把钱花光
return max(_[1] for _ in dp[n])
if __name__ == "__main__":
# Add your test cases here
test1 = [
[71, -51, 150],
[40, 50, 100],
[40, 50, 100],
[30, 30, 70],
[30, 30, 70],
[30, 30, 70],
]
print(solution(6, 100, 100, test1) == 240)
test1 = [
[71, -51, 150],
[40, -50, 100],
[40, -50, 100],
[30, -30, 70],
[30, -30, 70],
[30, -30, 70],
]
print(solution(6, 100, 100, test1) == 210)
test1 = [[23, 24, 23], [22, 7, 15], [14, 19, 20], [23, 25, 10],
[22, 17, 23], [9, 4, 20], [14, 4, 10], [24, 11, 12]]
print(solution(8, 15, 24, test1))