IPO问题–获得最大收益(贪心策略)

题目

输入:
参数1,正数数组costs 参数2,正数数组profits 参数3,正数k 参数4,正数m
costs[i]表示i号项目的花费
profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润)
k表示你不能并行、只能串行的最多做k个项目
m表示你初始的资金
说明:
你每做完一个项目,马上获得的收益,可以支持你去做下一个项目。
输出:
你最后获得的最大钱数。

实现思路

按照贪心策略 首先我们根据给定的初始基金可以找到我们能做的项目,之后得找到这些能做的项目中利润最高的,算上花费之后的利润我们又可以去找我们能做的其他项目,之后操作一样。
具体实现:
1.构建两个优先队列。一个是按照基金的构造小根堆,一个是按照利润构造的大根堆
2.将所有元素构建成对象利用比较器进行相应的构建堆的过程
3.将所有对象加入基金小根堆
4.如果基金小根堆里的基金小于等于我们给定的初始基金,将其弹出并加入利润大根堆中。
5.此时利润大根堆中一定就是我们需要的利润最高的解,累加利润并弹出。
6.重复4步骤 直到找到了k个解

代码


/**
 * @description: IPO问题–获得最大收益
 * @Author MRyan
 * @Date 2020/6/12 19:26
 * @Version 1.0
 */

/**
 * 实现思路: 按照贪心策略 首先我们根据给定的初始基金可以找到我们能做的项目,之后得找到这些能做的项目中利润最高的,算上花费之后的利润我们又可以去找我们能做的其他项目,之后操作一样。
 * 具体实现:
 * 1.构建两个优先队列。一个是按照基金的构造小根堆,一个是按照利润构造的大根堆
 * 2.将所有元素构建成对象利用比较器进行相应的构建堆的过程
 * 3.将所有对象加入基金小根堆
 * 4.如果基金小根堆里的基金小于等于我们给定的初始基金,将其弹出并加入利润大根堆中。
 * 5.此时利润大根堆中一定就是我们需要的利润最高的解,累加利润并弹出。
 * 6.重复4步骤 直到找到了k个解
 */
public class code_11 {

    public static void main(String[] args) {

        List<CP> lists = new ArrayList<>();
        lists.add(new CP(3, 9));
        lists.add(new CP(6, 20));
        lists.add(new CP(8, 14));
        lists.add(new CP(100, 200));
        int answer = answer(lists, 3, 40);
        System.out.println(answer);

    }

    /**
     * @param lists
     * @param k     只能做4个项目
     * @param m     初始资金
     */
    private static int answer(List<CP> lists, int k, int m) {
        int mm = m;
        //按初始基金构建小根堆
        PriorityQueue<CP> queueConst = new PriorityQueue<>(new CompareConst());
        //按利润构建大根堆
        PriorityQueue<CP> queueProfit = new PriorityQueue<>(new COmpareProfit());
        for (CP cp : lists) {
            queueConst.add(cp);
        }
        //当queueConst中有小于等于初始基金时弹出放入queueProfit中
        //只取k个最优解
        while (k > 0) {
            while ((queueConst.peek()).cost <= mm) {
                queueProfit.add(queueConst.poll());
            }
            //防止空指针
            if (queueProfit.isEmpty() || queueConst.isEmpty()) {
                break;
            }
            //输出测试
            CP text = queueProfit.peek();
            //现有的算上利润的钱 纯利润
            mm += text.profit;
            System.out.println("const: " + text.cost + " profit: " + text.profit + " now Money: " + mm);
            queueProfit.poll();
            k--;
        }
        return mm;
    }


    /**
     * 按照初始基金构造小根堆结构  初始资金小的在堆顶
     */
    private static class CompareConst implements Comparator<CP> {

        @Override
        public int compare(CP cp1, CP cp2) {
            if (cp1.cost < cp2.cost) {
                return -1;
            } else if (cp1.cost > cp2.cost) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    /**
     * 按照利润构造大根堆结构 利润最高的在堆顶
     */
    private static class COmpareProfit implements Comparator<CP> {

        @Override
        public int compare(CP cp1, CP cp2) {
            if (cp1.profit < cp2.profit) {
                return 1;
            } else if (cp1.profit > cp2.profit) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public static class CP {
        //初始资金
        private int cost;
        //获得利润
        private int profit;

        public CP(int cost, int profit) {
            this.cost = cost;
            this.profit = profit;
        }
    }
}


猜你喜欢

转载自blog.csdn.net/qq_35416214/article/details/106768021