【数据结构与算法】

代价数组(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;
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值