题目:
输入: 正数数组costs、正数数组profits、正数K、正数M costs[i]表示i号项目的花费 profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润) K表示你只能串行的最多做k个项目 M表示你初始的资金 说明: 每做完一个项目,马上获得的收益,可以支持你去做下一个项目。不能并行的做项目。 输出:你最后获得的最大钱数。
1、贪心解决方案
1.1、思路:
1、准备一个小根堆(项目花费),一个大根堆(项目利润)。
2、按照花费排序,加入到小根堆中
3、每次拿着本金去小根堆里面去判断,把小于等于本金的项目都取出来,然后把这些项目放入到大根堆里面,此时大根堆中堆顶的项目就是需要做的项目,每次都这样重试,直至循环结束
1.2、代码:
/**
* 求最后获得的最大钱数
*
* @param K 做项目的次数
* @param W 本金
* @param Profits 利润集合
* @param Capital 花费集合
*/
public static int findMaximizedCapital(int K, int W, int[] Profits, int[] Capital) {
//小根堆(花费),项目花费最小的在堆顶
PriorityQueue<Program> minCostQ = new PriorityQueue<>(new MinCostComparator());
//大根堆(利润),利润最大的在堆顶
PriorityQueue<Program> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());
//按照花费排序,加入到小根堆中
for (int i = 0; i < Profits.length; i++) {
minCostQ.add(new Program(Profits[i], Capital[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;
}
public static class Program {
//利润
public int p;
//花费
public int c;
public Program(int p, int c) {
this.p = p;
this.c = c;
}
}
public static class MinCostComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o1.c - o2.c;
}
}
public static class MaxProfitComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o2.p - o1.p;
}
}