代价数组(cost):【, , , , , ,】
利润数组(profit):【 , , , , , ,】
对应位置: 0,1, 2, 3,4, 5
对应位置的数值,就是它的花费,以及它的利润。最后获得的钱是代价+利润。
给定初始资金是W(初金)100,一次只能做一个项目,在能做k个项目(最多k个)的情况下,获取的最大收益是?
解题思路:
1、数据结构:
一个数组里,存放着一个个的项目。每个项目包含cost和profit
2、准备一个小根堆,谁的花费低,谁来到头部,依次弹出头部,然后再将它放到一个大根堆里面,大根堆是谁的收益高,谁在顶部。
初始资金是100,一开始,所有的项目都可以进小根堆。依次弹出头部,所以项目中花费低的会弹出。所有比100小的,从小根堆里弹出来,进入大根堆。在大根堆里,按照收益这个维度来排,谁高就谁在顶部。初始资金是100,现在小根堆里就都被弹出来了,进入大根堆,当弹到不能再弹的时候,我所有可以选择的项目都进大根堆了。而没有弹出的项目,是当前无法做的。所以小根堆就是所有的项目 ,大根堆是解锁的项目。看资金100可以解锁哪些项目,在小根堆中依次弹出,放到大根堆里,这里面就是解锁的项目。然后在大根堆里把头部的项目拿出来,这个是所有解锁的项目里收益最高的。做完这个项目,初始资金就会增加。再看小根堆里哪些项目可以被解锁,继续重复刚才的,
每个node就是我的项目,里面有我的收益和花费。
收益高的比较器:
收益低的比较器:
生成最大的钱数:
Node类型的数组,放了所有的项目。每个项目中有两个维度,一个是它的收益是多少,一个是它的花费是多少。
准备一个谁小谁放在上面的小根堆,(一个优先队列,里面包含一个谁小谁放在顶部的比较器),
再准备一个谁大谁放在上面的大根堆,(一个优先队列,里面包含谁大谁放在上面的比较器)。
把所有的项目,加到小根堆里面去:
依次做项目,最多做k个,
如果小根堆堆顶的钱小于我当前的钱,(说明小根堆堆顶的这个是我可以做的,就相当于解锁)
将小根堆里的项目弹出,按照利润谁大,谁就放在大根堆的顶部,放进去。能解锁就解锁,否则就以0个项目,从小根堆里出来。
如果你发现还没做到k个项目,大根堆里面就空了,说明初始资金无法解锁新的项目了,这个时候就直接返回w值即可。
用W加上我大根堆里的利润,得到你现在的钱。
public class Code_03_IPO {
public static class Node {
public int p;
public int c;
public Node(int p, int c) {
this.p = p;
this.c = c;
}
}
public static class MinCostComparator implements Comparator<Node> {
@Override
public int compare(Node o1, Node o2) {
return o1.c - o2.c;
}
}
public static class MaxProfitComparator implements Comparator<Node> {
@Override
public int compare(Node o1, Node o2) {
return o2.p - o1.p;
}
}
public static int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
Node[] nodes = new Node[Profits.length];
for (int i = 0; i < Profits.length; i++) {
nodes[i] = new Node(Profits[i], Capital[i]);
}
PriorityQueue<Node> minCostQ = new PriorityQueue<>(new MinCostComparator());
PriorityQueue<Node> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());
for (int i = 0; i < nodes.length; i++) {
minCostQ.add(nodes[i]);
}
for (int i = 0; i < k; i++) {
while (!minCostQ.isEmpty() && minCostQ.peek().c <= W) {
maxProfitQ.add(minCostQ.poll());
}
if (maxProfitQ.isEmpty()) {
return W;
}
W += maxProfitQ.poll().p;
}
return W;
}
}