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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章