Suppose LeetCode will start its IPO soon. In order to sell a good price of its shares to Venture Capital, LeetCode would like to work on some projects to increase its capital before the IPO. Since it has limited resources, it can only finish at most k distinct projects before the IPO. Help LeetCode design the best way to maximize its total capital after finishing at most k distinct projects.
You are given several projects. For each project i, it has a pure profit Pi and a minimum capital of Ci is needed to start the corresponding project. Initially, you have W capital. When you finish a project, you will obtain its pure profit and the profit will be added to your total capital.
To sum up, pick a list of at most k distinct projects from given projects to maximize your final capital, and output your final maximized capital.
Example 1:
Input: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1]. Output: 4 Explanation: Since your initial capital is 0, you can only start the project indexed 0. After finishing it you will obtain profit 1 and your capital becomes 1. With capital 1, you can either start the project indexed 1 or the project indexed 2. Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital. Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4.
Note:
- You may assume all numbers in the input are non-negative integers.
- The length of Profits array and Capital array will not exceed 50,000.
- The answer is guaranteed to fit in a 32-bit signed integer.
给定初始资金和K个项目,每个项目需要一定的启动资金C和收益P,求最后的资金最多是多少?
题意理解:如果有一个项目的启动资金大于当前的资金数,那么这个项目是做不了的。如果有多个项目可以做(现在的钱够他的启动资金),那么应该选择收益最大的那个项目去做。做完之后,现在的钱最多,才能以后尽可能的多做项目。
默认:如果一个项目启动资金大于收益,根本没有做的必要,因此排除这种情况。
思路:
首先建立一个最小堆(启动资金最小堆),启动资金小的排在前面,然后根据当前的资金数,将可以做的项目加入到另外一个堆(收益最大堆)中,这个堆按照收益排成最大堆。弹出堆顶的项目做掉。当前的初始资金多了,第一个堆中可能有一些项目可以加入到第二堆中。然后重复上述过程。
什么时候算是结束呢?
收益最大堆里面的项目肯定可以做完
有两种情况:
(1)当前的资金数在启动资金堆里面找不到可以做的项目,这时只能做收益堆里面的项目。如果收益堆里面的项目全部做完了,启动资金里面还有一些耗资庞大的项目做不了,这个时候就返回总收益。即sum<heap1.top()&&heap2.empty()
(2)如果启动堆空了,那就做收益堆里面的项目,直到做完。终止条件:heap1.empty()&&heap2.empty()
(3)还有一种情况,如果开始proMax就是空的,直接返回。
(4)做够了K个项目
以上条件穿插在循环当中
注意:启动最小堆的建立,不能简单的以启动资金排序,因为有两个启动资金相同的情况,这个时候应该把收益大的排在前面
同样的道理,如果两个收益相同,在收益堆中,应该把启动资金小的放在前面
注意:这里的收益是纯收益,是去除成本的
代码如下:
class Solution {
public:
int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
priority_queue<pro,vector<pro>,compareMin> capMin;//启动资金最小堆,还要注意的时
priority_queue<pro,vector<pro>,compareMax> proMax;//收益最大堆
for(int i=0;i<Profits.size();i++)
{
capMin.push({Profits[i],Capital[i]});//建立完整的启动资金最小堆
}
//修改或建立收益最大堆
while(k)
{
while(!capMin.empty()&&W>=capMin.top().capital)//每次一进循环就增加收益堆前面条件不需要判断 proMax.empty(),注意这里应该有等号
{
proMax.push(capMin.top());
capMin.pop();
}
if(proMax.empty()) return W;//这里返回是没有项目可做了
pro currentPro=proMax.top();
proMax.pop();
W+=currentPro.profits;
k--;
}
return W;//这里返回是做够了K个项目
}
struct pro{
int profits;
int capital;
};
//使用函数对象
struct compareMin{
bool operator()(const pro& a,const pro& b){
if(a.capital==b.capital) return a.profits<b.profits;//如果启动资金相同,把收益小的放在后面
return a.capital>b.capital;
}
};
struct compareMax{
bool operator()(const pro& a,const pro&b){
if(a.profits==b.profits) return a.capital>b.capital;//如果收益相同,应该把启动资金大的放在后面
return a.profits<b.profits;
}
};
};