输入:
参数1, 正数数组costs
参数2, 正数数组profits
参数3,正数k
参数4, 正数m
costs[i]表示i号项目的花费
profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润)
k表示你不能并行、 只能串行的最多做k个项目
m表示你初始的资金
说明: 你每做完一个项目, 马上获得的收益, 可以支持你去做下一个 项目。
输出: 你最后获得的最大钱数。
将每个项目的成本和利润放到一起,
然后准备一个大根堆,一个小根堆
首先小根堆:按照成本的大小排序,然后将成本小于w的项目全部弹出,加入到大根堆中(大根堆是按照利润的大小进行排序)
然后将大根堆中的顶点值弹出,即是本次选择的项目,然后本金m增加,k减少一次,继续下一次
如果小根堆不能弹出项目(成本大于现在的本金)时,继续从大根堆弹出项目。进行下一次,直到k为0
public class IPO {
public static class Item {
private int cost;
private int profit;
public Item(int cost, int profit){
this.cost = cost;
this.profit = profit;
}
}
//按照最小成本构建的小根堆中
public static class MinheapComparator implements Comparator<Item>{
@Override
public int compare(Item o1, Item o2) {
return o1.cost - o2.cost;
}
}
//按照最大收益构建的大根堆中
public static class MaxheapComparator implements Comparator<Item>{
@Override
public int compare(Item o1, Item o2) {
return o2.profit - o1.profit;
}
}
public int maxProfit(int[] costs, int[] profits, int k, int m){
if(costs == null || profits == null || costs.length != profits.length || k <= 0) return 0;
//用来将项目放到一个按照最小成本构建的小根堆中
PriorityQueue<Item> itemsByMinCost = new PriorityQueue<>( new MinheapComparator() );
for(int i = 0; i < costs.length; i++){
itemsByMinCost.add(new Item(costs[i], profits[i]));
}
//用来盛放按照当前资金可以承受的范围内的项目,且按照最大收益构建的大根堆中(从小根堆中弹出的)
PriorityQueue<Item> itemsByMaxProfit = new PriorityQueue<>( new MaxheapComparator() );
//错误的循环,下面那个是对的
//这个判断条件有问题,当小根堆中的元素全部入大根堆的队列中,且还未达到k时,此时就会跳出循环,这样是不对的
while(itemsByMinCost.size() > 0 && k > 0){
while(itemsByMinCost.peek().cost <= m) {
itemsByMaxProfit.add( itemsByMinCost.poll() );
}
if(itemsByMaxProfit.isEmpty() && itemsByMinCost.peek().cost > m) break;
if(itemsByMaxProfit.size() > 0){
m += itemsByMaxProfit.poll().profit;
k--;
}
}
//这个循环判断条件是对的,上面那个是不对的
for(int i = 0; i < k; i++){
while(!itemsByMaxProfit.isEmpty() && itemsByMinCost.peek().cost <= m){
itemsByMaxProfit.add(itemsByMinCost.poll());
}
if(itemsByMaxProfit.isEmpty()) break;
m += itemsByMaxProfit.poll().profit;
}
return m;
}
}