日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

算法练习day14——190402(贪心:切金条、做项目、会议室安排)

發(fā)布時(shí)間:2024/10/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法练习day14——190402(贪心:切金条、做项目、会议室安排) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 切金條

一塊金條切成兩半,是需要花費(fèi)和長(zhǎng)度數(shù)值一樣的銅板的。

比如長(zhǎng)度為20的金條, 不管切成長(zhǎng)度多大的兩半,都要花費(fèi)20個(gè)銅板。

一群人想整分整塊金條, 怎么分最省銅板?

例如,給定數(shù)組{10,20,30}, 代表一共三個(gè)人, 整塊金條長(zhǎng)度為10+20+30=60。金條要分成10,20,30三個(gè)部分。 如果, 先把長(zhǎng)度60的金條分成10和50, 花費(fèi)60。再把長(zhǎng)度50的金條分成20和30,花費(fèi)50。一共花費(fèi)110銅板。但是如果先把長(zhǎng)度60的金條分成30和30,花費(fèi)60再把長(zhǎng)度30金條分成10和20,花費(fèi)30一共花費(fèi)90銅板。

輸入一個(gè)數(shù)組, 返回分割的最小代價(jià)。

1.1 分析

這是一個(gè)標(biāo)準(zhǔn)的哈夫曼問(wèn)題:兩個(gè)葉節(jié)點(diǎn)合并的時(shí)候,代價(jià)就是葉節(jié)點(diǎn)之和。

給定10,20,30,構(gòu)成一個(gè)數(shù),使得所有非葉節(jié)點(diǎn)之和最小。

解題思路:

給定一組數(shù):{1,2,6,4,3,7,1,8},然后將這組數(shù)構(gòu)成一個(gè)小根堆。每次從小根堆中拿出兩個(gè)數(shù)。

第一次拿的肯定是兩個(gè)1。這兩個(gè)1生成一個(gè)節(jié)點(diǎn),代價(jià)為2。然后把這個(gè)2扔回到小根堆中。

接著拿出兩個(gè)數(shù):兩個(gè)2,這兩個(gè)2合并的代價(jià)為4,然后將4扔回到小根堆中。。。。

最終得到的結(jié)果:

貪心:在所有的數(shù)中總是拿兩個(gè)最小的。

此題中,切割的順序是根據(jù)形成的樹(shù)由上到下的。

1.2 代碼實(shí)現(xiàn)

public static int lessMoney(int[] arr) {PriorityQueue<Integer> pQ = new PriorityQueue<>();//系統(tǒng)實(shí)現(xiàn)的堆for (int i = 0; i < arr.length; i++) {pQ.add(arr[i]);//所有的數(shù)入堆}int sum = 0;int cur = 0;while (pQ.size() > 1) {//堆中元素只有一個(gè)時(shí),停止cur = pQ.poll() + pQ.poll();//每次取兩個(gè),求和即為代價(jià)sum += cur;//當(dāng)前和累加pQ.add(cur);//將和放回堆中}return sum; }

2. 項(xiàng)目收益最大

輸入:

  • 參數(shù)1, 正數(shù)數(shù)組costs;
  • 參數(shù)2, 正數(shù)數(shù)組profits;
  • 參數(shù)3,正數(shù)k;
  • 參數(shù)4, 正數(shù)w;
  • costs[i]:表示i號(hào)項(xiàng)目的花費(fèi);
  • profits[i]:表示i號(hào)項(xiàng)目在扣除花費(fèi)之后還能掙到的錢(qián)(利潤(rùn));
  • k表示你不能并行、 只能串行的最多做k個(gè)項(xiàng)目,即一次只能做一個(gè)項(xiàng)目,只能做夠k個(gè);
  • w表示你初始的資金。

說(shuō)明: 你每做完一個(gè)項(xiàng)目,馬上獲得的收益,可以支持你去做下一個(gè)項(xiàng)目。

輸出: 你最后獲得的最大錢(qián)數(shù)。

2.1 分析

將costs數(shù)組和profits數(shù)組合并為一個(gè)以項(xiàng)目為單位的數(shù)組:

[項(xiàng)目1(cost1,profit1),項(xiàng)目2(cost2,profit2),...]

然后根據(jù)這個(gè)項(xiàng)目數(shù)組,建立一個(gè)小根堆,花費(fèi)最小的在頂部。

在小根堆中,依次彈出花費(fèi)小于w的頭部。

將彈出的項(xiàng)目放入大根堆中,收益最大的在頂部。

然后選擇大根堆頂部的項(xiàng)目執(zhí)行,此項(xiàng)目一定是所有可做項(xiàng)目中收益最大的。

做完這個(gè)項(xiàng)目后,資金變多為w'(增加了此項(xiàng)目的收益),然后繼續(xù)彈出小根堆中花費(fèi)小于w'的頭部,放到大根堆中,依收益排序。

這樣一直做k個(gè)結(jié)束。

2.2 舉例

2.3 代碼實(shí)現(xiàn)

import java.util.Comparator; import java.util.PriorityQueue;public class Code_03_IPO {public static class Node {//每個(gè)Node就是一個(gè)項(xiàng)目public int p;//收益public int c;//花費(fèi)public Node(int p, int c) {this.p = p;this.c = c;}}public static class MinCostComparator implements Comparator<Node> {@Overridepublic int compare(Node o1, Node o2) {return o1.c - o2.c;}}public static class MaxProfitComparator implements Comparator<Node> {@Overridepublic 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++) {//合并兩個(gè)數(shù)組,以項(xiàng)目為單位重建一個(gè)數(shù)組nodes[i] = new Node(Profits[i], Capital[i]);}PriorityQueue<Node> minCostQ = new PriorityQueue<>(new MinCostComparator());//根據(jù)花費(fèi)建立的小根堆PriorityQueue<Node> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());//根據(jù)收益建立的大根堆for (int i = 0; i < nodes.length; i++) {minCostQ.add(nodes[i]);//建小根堆}for (int i = 0; i < k; i++) {//項(xiàng)目數(shù)小于kwhile (!minCostQ.isEmpty() && minCostQ.peek().c <= W) {maxProfitQ.add(minCostQ.poll());//彈出堆頂花費(fèi)小于已有資金的項(xiàng)目,加入大根堆中}if (maxProfitQ.isEmpty()) {return W;//大根堆為空,即沒(méi)有可做的項(xiàng)目,返回總資金}W += maxProfitQ.poll().p;//執(zhí)行大根堆堆頂?shù)娜蝿?wù),增加總資金}return W;} }

3.會(huì)議室安排

一些項(xiàng)目要占用一個(gè)會(huì)議室宣講, 會(huì)議室不能同時(shí)容納兩個(gè)項(xiàng)目的宣講。 給你每一個(gè)項(xiàng)目開(kāi)始的時(shí)間和結(jié)束的時(shí)間(給你一個(gè)數(shù)組, 里面 是一個(gè)個(gè)具體的項(xiàng)目), 你來(lái)安排宣講的日程, 要求會(huì)議室進(jìn)行的宣講的場(chǎng)次最多。 返回這個(gè)最多的宣講場(chǎng)次。

3.1 分析

貪心策略

  • 按開(kāi)始時(shí)間安排,早就安排;——得不到最優(yōu)解,有可能很早開(kāi)始,然后占全天。
  • 按持續(xù)時(shí)間安排,持續(xù)時(shí)間短,安排它;——得不到最優(yōu)解
  • C比A和B時(shí)間都短,但是安排了C,A和B都不能安排了。
  • 應(yīng)該按照那個(gè)早結(jié)束來(lái)安排項(xiàng)目。
  • 選擇最早結(jié)束的項(xiàng)目;
  • 淘汰掉因?yàn)樽鲞@個(gè)項(xiàng)目,而不能做的項(xiàng)目。
  • 接著再選結(jié)束時(shí)間最早的項(xiàng)目,...。
  • 3.2 代碼實(shí)現(xiàn)

    import java.util.Arrays; import java.util.Comparator;public class BestArrange {public static class Program {public int start;public int end;public Program(int start, int end) {this.start = start;this.end = end;}}public static class ProgramComparator implements Comparator<Program> {@Overridepublic int compare(Program o1, Program o2) {return o1.end - o2.end;//結(jié)束時(shí)間早的安排在前面}}public static int bestArrange(Program[] programs, int start) {Arrays.sort(programs, new ProgramComparator());int result = 0;//完成的項(xiàng)目數(shù)for (int i = 0; i < programs.length; i++) {if (start <= programs[i].start) {//開(kāi)始時(shí)間晚于給定的時(shí)間,則可以開(kāi)始這個(gè)項(xiàng)目result++;start = programs[i].end;//將下一次開(kāi)始時(shí)間設(shè)為當(dāng)前已完成的項(xiàng)目結(jié)束時(shí)的時(shí)間}}return result;} } 與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的算法练习day14——190402(贪心:切金条、做项目、会议室安排)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。