1 动态规划
dp[i][j]表示前i个项目中做j个项目带来的最大收益
需要先对所有的项目按照启动资本排序
但是结果超时了:32 / 35 个通过测试用例
class Solution:
def findMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int:
n = len(profits)
tasks = [(capital[i], profits[i]) for i in range(n)]
tasks.sort(key=lambda x: x[0])
# dp[i][j]表示前i个项目中做j个项目带来的最大收益
dp, max_first = [[0] * (k + 1) for _ in range(n + 1)], 0
# 初始化k为1的dp数组:从前i个项目中做1个项目带来的最大收益——要挑能负担的起,且利润最大的那个项目
for i in range(n):
if w >= tasks[i][0] and max_first < tasks[i][1]:
max_first = tasks[i][1]
dp[i + 1][1] = max_first
for ki in range(2, k + 1):
for i in range(1, n + 1):
# 只能从前i个项目中选,如果需要选出的数量已经超过候选的项目数,则无项目可选,不能继续扩大利润
if i < ki:
dp[i][ki] = dp[i][ki - 1]
else:
# 如果从前i-1个项目中,选择ki-1个,获得的最大收益,加上初始资本,足以支付当前项目(第i-1个)的成本
if w + dp[i - 1][ki - 1] >= tasks[i - 1][0]:
dp[i][ki] = max(dp[i - 1][ki - 1] + tasks[i - 1][1], dp[i - 1][ki])
else:
dp[i][ki] = dp[i - 1][ki]
return w + dp[n][k]
2 贪心+堆
实际上也确实没必要用动规,这道题可以直接上贪心:每次都从可选的范围内选择利润最大的task即可
执行用时:92 ms, 在所有 Python3 提交中击败了99.33% 的用户
内存消耗:35.3 MB, 在所有 Python3 提交中击败了54.67% 的用户
通过测试用例:35 / 35
class Solution:
def findMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int:
if w >= max(capital):
return w + sum(heapq.nlargest(k, profits))
n = len(profits)
curr = 0
tasks = [(capital[i], profits[i]) for i in range(n)]
tasks.sort(key=lambda x: x[0])
pq = []
# 贪心,每次取能负担的起的最大利润的项目,一共取k次
for _ in range(k):
# 每一轮挑选项目,都先根据当前已经更新(增加)了的w,把(增加了资本以后)能负担的起的项目(的利润)依次(已经排序)入堆
while curr < n and tasks[curr][0] <= w:
# Python不支持大根堆,所以取相反数,用小根堆替代大根堆
heapq.heappush(pq, -tasks[curr][1])
curr += 1
if pq:
# 当前队列里还有可选的项目。堆里是利润的相反数,所以这里要减去
w -= heapq.heappop(pq)
else:
# 当前队列里已无项目可选
break
return w