zoukankan      html  css  js  c++  java
  • 贪心算法--堆--成本与利润

    输入:

    参数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;
        }
    }
    

      

  • 相关阅读:
    javaapplicationWeb application setup on Ubuntu VPS
    内容中断随想录(risc cpu的那些事)
    算法线性编程珠玑读书笔记之----->使用线性算法求解连续子序列的最大和
    classnull100
    安装javaUbuntu下安装JDK1.6,并将之设为默认的JDK
    筛选实现C++实现筛选法
    调试设置移动端Web开发环境搭建实践
    路由器交换机[置顶] 路由器和交换机的综合实验⑵
    卡数字怀念的东西:魔方
    密码配置配置SSH免密码登陆
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/8962566.html
Copyright © 2011-2022 走看看