问题
标准贪心问题
输入:
参数1,正数数组costs ;
参数2,正数数组profits ;
参数3, 正数k ;
参数4,正数m ;
costs[i]表示i号项目的花费,
profits[i]表示i号项目在扣除花 费之后还能挣到的钱(利润),
k表示你不能并行、只能串行的最多 做k个项目,
m表示你初始的资金 。
说明:你每做完一个项目,马上获得的收益,可以支持你去做下 一个 项目。 输出: 你最后获得的最大钱数。
分析
注意!!!
这个题目的意思是,每次做完是不减成本的,只考虑在能做范围内收益最高!!!
首先每个项目包括两个属性:花费成本 cost 和利润 profile,然后将所有的项目放入数组中。
然后将数组中所有的项目按照花费成本的大小形成一个小根堆,接着挨着从小根堆中弹出头部,只要花费成本小于初始资金(W)就都弹出,(弹出来的表示在当前资金下可以做的任务),然后将弹出的元素按照收益的高低放入大根堆中(则收益越高越优先做),每次只做大根堆的堆头部的任务,做完任务之后初始资金发生变化,再次从小根堆中弹出符合的元素进入大根堆,以此类推。直到大根堆中没有元素或者达到了最大 K 次就结束。
示例:以下任务的初始资金为:7
cost: 5 10 6 20
profile:3 2 4 9
首先将所有的项目放入小根堆,然后通过比较 cost 和初始资金,则首先放入大根堆中是: 6,4 和 5,3,先做堆顶项目6,4,做完之后收益变为:11,则任务 10,2 可以做了,现在大根堆中为:5,3;10,2,先做 5,3 任务,收益变为 14,没有新的任务可以加入大根堆中,则继续做大根堆中任务:10,2,昨晚之后收益变为:16,还是没有新的项目可以加入大根堆,这时候大根堆没有任务可以完成了,则最终停止。
实现
package MyExc;
import org.junit.Test;
import java.util.*;
//定义大根堆比较器
class myIntegerCpmparator implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
}
public class MaxProfits {
public int maxProfits(int[] conts,int[] profits,int k,int m){
//定义返回的最大利润
//int maxProfits = 0;
//定义进行的项目个数
int i = 0;
//定义当前的可用资金
int M = m;
PriorityQueue<Integer> BigHeap = new PriorityQueue<>(new myIntegerCpmparator());
PriorityQueue<Integer> SmallHeap = new PriorityQueue<>();
//建立map
Map<Integer,Integer> map = new HashMap<>();
for(int n = 0;n<conts.length;n++){
map.put(conts[n],profits[n]);
}
//先按照成本进入小根堆
for(int j:conts){
SmallHeap.add(j);
}
while(i<k&&!SmallHeap.isEmpty()){
//满足条件弹出小根堆全部进入大根堆
while(SmallHeap.peek()<M){
BigHeap.add(map.get(SmallHeap.poll()));
}
//大根堆弹出,更新可用资金
if(BigHeap.isEmpty())
break;
M +=BigHeap.poll();
i++;
}
return M;
}
@Test
public void run(){
int[] costs = {5,10,6,20};
int[] profits = {3,2,4,9};
int res = maxProfits(costs,profits,4,7);
System.out.println(res);
}
}