贪心算法--堆--成本与利润
输入:
参数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; } }