貪心思想總結

来源:https://www.cnblogs.com/PlayerSS05/archive/2022/05/25/16308823.html
-Advertisement-
Play Games

日期:2022年5月25日 註:本博客僅供參考 概念與思路 貪心演算法是指在對某一問題求解時,總是作出當前情況下的最優選擇。因此,貪心演算法考慮的不是整個問題的最優解,演算法得到的是在某一局部環境下的最優解。 貪心演算法的一般思路為: 把要求解的問題分為若幹個子問題; 對每個子問題求解,得到子問題的局部最優 ...


日期:2022年5月25日

註:本博客僅供參考


 

概念與思路

貪心演算法是指在對某一問題求解時,總是作出當前情況下的最優選擇。因此,貪心演算法考慮的不是整個問題的最優解,演算法得到的是在某一局部環境下的最優解。

貪心演算法的一般思路為:

  1. 把要求解的問題分為若幹個子問題;
  2. 對每個子問題求解,得到子問題的局部最優解;
  3. 把得到的局部最優解合為原來問題的一個解。

註意事項(尤為重要)

  • 貪心演算法能省去要窮盡所有可能二耗費的大量時間,但它沒有考慮整個問題下的情景,因此通過該演算法得到的答案,不能確定是否為整個問題的最優解。也就是說,如果要使用貪心演算法,應該在證明出通過貪心得出的答案就是最優解後再使用。
  • 貪心演算法一般只用於求最大或最小值。
  • 貪心演算法只能確定某些問題的可行性範圍。

代碼與應用

部分背包問題(P2240)

題目描述

阿裡巴巴走進了裝滿寶藏的藏寶洞。藏寶洞裡面有N(N≤100)堆金幣,第i堆金幣的總重量和總價值分別是 mi,vi(1≤mi,vi≤100)。阿裡巴巴有一個承重量為T(T≤1000)的背包,但並不一定有辦法將全部的金幣都裝進去。他想裝走儘可能多價值的金幣。所有金幣都可以隨意分割,分割完的金幣重量價值比(也就是單位價格)不變。請問阿裡巴巴最多可以拿走多少價值的金幣?

輸入格式

第一行兩個整數 N,T。

接下來N行,每行兩個整數 mi,vi

輸出格式

一個實數表示答案,輸出兩位小數。

代碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=110;
 4 int n,t;
 5 struct node{
 6     int m;
 7     int v;
 8 };
 9 node a[N];
10 bool operator <(node a,node b){
11     return a.v*b.m>b.v*a.m;
12     /*用金幣價值與金幣質量的比值來比較不同金幣的實際價值
14     return a.v*b.m>b.v*a.m的效果等同於return a.v/a.m>b.v/b.w,但由於在C++中“/”意為整除,所以需要使用其他方法代替除法*/
15 }
16 int main(){
17     scanf("%d%d",&n,&t);
18     for(int i=1;i<=n;++i)
19     {
20         scanf("%d%d",&a[i].m,&a[i].v);
21     }
22     sort(a+1,a+1+n);//重定義的的“<”會在這裡用到
23     double ans=0;
24     for(int i=1;i<=n;++i)
25     {
26         if(a[i].m<=t)//當金幣質量小於背包能容納的剩餘質量時,將這堆金幣全部放進去
27         {
28             ans+=a[i].v;
29             t-=a[i].m;
30         }else{//當金幣質量大於背包能容納的剩餘質量時,用這種金幣將背包的剩餘部分填滿並結束迴圈
31             ans+=1.0*t*a[i].v/a[i].m;
32             break;
33         }
34     }
35     printf("%.2lf",ans);
36     return 0;
37 }         

排隊接水(P1223)

題目描述

n個人在一個水龍頭前排隊接水,假如每個人接水的時間為Ti,請編程找出這n個人排隊的一種順序,使得n個人的平均等待時間最小。

輸入格式

第一行為一個整數n

第二行n個整數,第i個整數Ti 表示第i個人的等待時間Ti

輸出格式

輸出文件有兩行,第一行為一種平均時間最短的排隊順序;第二行為這種排列方案下的平均等待時間(輸出結果精確到小數點後兩位)。

代碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1000100;
 4 int n;
 5 double ave=0;
 6 struct node{
 7     int t;
 8     int code;
 9 };
10 bool operator <(node a,node b){
11     return a.t<b.t;//升序排列
12 }
13 node T[N];
14 int main(){
15     scanf("%d",&n);
16     for(int i=1;i<=n;++i)
17     {
18         scanf("%d",&T[i].t);
19         T[i].code=i;
20     }
21     sort(T+1,T+1+n);
22     for(int i=1;i<=n;++i)
23     {
24         for(int j=0;j<i;++j)
25         {
26             ave+=T[j].t;
27         }
28         printf("%d ",T[i].code);
29     }
30     ave/=n;//平均等待時間為所有人需要等待的時間與人數的比值
31     printf("\n%.2lf",ave);
32     return 0;
33 }

均分紙牌(P1031)

題目描述

NN堆紙牌,編號分別為 1,2,…,N。每堆上有若幹張,但紙牌總數必為N的倍數。可以在任一堆上取若幹張紙牌,然後移動。

移牌規則為:在編號為1堆上取的紙牌,只能移到編號為2的堆上;在編號為N的堆上取的紙牌,只能移到編號為N-1的堆上;其他堆上取的紙牌,可以移到相鄰左邊或右邊的堆上。

現在要求找出一種移動方法,用最少的移動次數使每堆上紙牌數都一樣多。

例如N=4,4堆紙牌數分別為:

9817④6

移動3次可達到目的:

從 ③ 取4張牌放到 ④ (9,8,13,10)-> 從 ③ 取3張牌放到 ②(9,11,10,10)-> 從 ② 取1張牌放到①(10,10,10,10)。

輸入格式

兩行

第一行為:NN堆紙牌,1N100)。

第二行為:A1,A2, … ,An (N堆紙牌,每堆紙牌初始數,1≤Ai10000)。

輸出格式

一行:即所有堆均達到相等時的最少移動次數。

代碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=110;
 4 int n,a[N],ave=0,sum=0;
 5 int main(){
 6     scanf("%d",&n);
 7     for(int i=1;i<=n;++i)
 8     {
 9         scanf("%d",&a[i]);
10         ave+=a[i];
11     }
12     ave/=n;//紙牌平均數恆為定值
13     for(int i=1;i<=n;++i)
14     {
15         if(a[i]!=ave)//如果這堆紙牌不是平均值,向右邊放a[i+1]-ave張紙牌
16         {
17             a[i+1]+=a[i]-ave;
18             ++sum;
19         }
20     }
21     printf("%d",sum);
22     return 0;
23 }

鋪設道路(P5019)

題目描述

春春是一名道路工程師,負責鋪設一條長度為n的道路。

鋪設道路的主要工作是填平下陷的地表。整段道路可以看作是n塊首尾相連的區域,一開始,第i塊區域下陷的深度為di

春春每天可以選擇一段連續區間[L,R],填充這段區間中的每塊區域,讓其下陷深度減少1。在選擇區間時,需要保證,區間內的每塊區域在填充前下陷深度均不為0

春春希望你能幫他設計一種方案,可以在最短的時間內將整段道路的下陷深度都變為0

輸入格式

輸入文件包含兩行,第一行包含一個整數n,表示道路的長度。 第二行包含n個整數,相鄰兩數間用一個空格隔開,第i個整數為di

輸出格式

輸出文件僅包含一個整數,即最少需要多少天才能完成任務。

代碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=100100;
 4 int n,d[N],sum=0;
 5 int main(){
 6     scanf("%d",&n);
 7     for(int i=1;i<=n;++i)
 8     {
 9         scanf("%d",&d[i]);
10     }
11     sum+=d[1];
12     for(int i=2;i<=n;++i)
13     {
14         if(d[i]>d[i-1])
15         {
16             sum+=d[i]-d[i-1];//如果後面大於前面,則共有d[i]-d[i-1]層需要單獨填掉(小於的部分可以和前面一起填掉)
17         }
18     }
19     printf("%d",sum);
20     return 0;
21 }

線段覆蓋(P1803)

題目描述

現在各大oj上有n個比賽,每個比賽的開始、結束的時間點是知道的。

yyy認為,參加越多的比賽,noip就能考的越好(假的)。

所以,他想知道他最多能參加幾個比賽。

由於y是蒟蒻,如果要參加一個比賽必須善始善終,而且不能同時參加2個及以上的比賽。

輸入格式

第一行是一個整數n,接下來n行每行是2個整數 ai,bi(ai<bi),表示比賽開始、結束的時間。

輸出格式

一個整數,表示最多參加的比賽數目。

代碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1000100;
 4 int n,sum=0,now=0;
 5 struct node{
 6     int a;
 7     int b;
 8 };
 9 bool operator <(node A,node B){
10     return A.b<B.b;
11 }
12 node m[N];
13 int main(){
14     scanf("%d",&n);
15     for(int i=1;i<=n;++i)
16     {
17         scanf("%d%d",&m[i].a,&m[i].b);
18     }
19     sort(m+1,m+n+1);
20     sum=1,now=1;//選中排序後的第一個比賽
21     for(int i=2;i<=n;++i)
22     {
23         if(m[i].a>=m[now].b)//如果下一個比賽開始時間在正在參加的比賽結束時間之後(相等也可以),則選中這個比賽
24         {
25             ++sum;
26             now=i;
27         }
28     }
29     printf("%d",sum);
30     return 0;
31 }

雷達安裝(P1325)

題目描述

假設海岸線是一條無限延伸的直線。它的一側是陸地,另一側是海洋。每一座小島是在海面上的一個點。雷達必須安裝在陸地上(包括海岸線),並且每個雷達都有相同的掃描範圍d。你的任務是建立儘量少的雷達站,使所有小島都在掃描範圍之內。

數據使用笛卡爾坐標系,定義海岸線為x軸。在x軸上方為海洋,下方為陸地。

如圖:

輸入格式

第一行包括2個整數n和d,n是島嶼數目,d是雷達掃描範圍。

接下來n行為島嶼坐標。

輸出格式

一個整數表示最少需要的雷達數目,若不可能覆蓋所有島嶼,輸出-1。

代碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1100;
 4 int n,d,x[N],y[N],now=0,sum=0;
 5 struct node{
 6     double L;
 7     double R;
 8 };
 9 bool operator <(node a,node b){
10     return a.R<b.R;
11 }
12 node a[N];
13 int main(){
14     scanf("%d%d",&n,&d);
15     for(int i=1;i<=n;++i)
16     {
17         scanf("%d%d",&x[i],&y[i]);
18         if(y[i]>d)//如果小島的縱坐標比雷達的半徑還要大,那麼就覆蓋不到這個小島,輸出-1並結束程式
19         {
20             printf("%d",-1);
21             return 0;
22         }
23         a[i].L=x[i]-sqrt(pow(d,2)-pow(y[i],2));
24         a[i].R=x[i]+sqrt(pow(d,2)-pow(y[i],2));
25         //計算出雷達可以覆蓋到這個小島的極限範圍區間(用勾股定理計算,斜邊為d,一個直角邊為y[i])
26     }
27     sort(a+1,a+1+n);
28     sum=1,now=1;//覆蓋到第一個小島,安放第一個雷達
29     for(int i=2;i<=n;++i)
30     {
31         if(a[i].L>a[now].R)//如果這兩個區間沒有公共部分,則安放下一個雷達
32         {
33             ++sum;
34             now=i;
35         }
36     }
37     printf("%d",sum);
38     return 0;
39 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這是 SFML 官方教程的翻譯&筆記 涉及的模塊有 系統模塊 視窗模塊 圖形模塊 ...
  • 實驗環境 本實驗搭建在虛擬機中。一臺伺服器作為DR兩台作為RS,還有一臺為後續內容會用到的備用機。 實驗環境示意圖: 1. 修改網路層VIP 修改DR,添加VIP 修改前: 修改後: 修改RS,修改ARP協議並添加VIP 1. 修改內核 此處的ens160改為自己網卡名稱。 echo 1 > /pr ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • docker安裝nacos 拉取版本對應鏡像 docker pull nacos/nacos-server:1.4.2 創建配置文件 vim /usr/local/nacos/init.d/custom.properties 修改配置文件 server.contextPath=/nacos serv ...
  • 如果你是Spring Boot用戶的話,一定有這樣的開發體驗,當我們要引入某個功能的時候,只需要在maven或gradle的配置中直接引入對應的Starter,馬上就可以使用了,而不需要像傳統Spring應用那樣寫個xml或java配置類來初始化各種Bean。 如果你有探索過這些Starter的原理 ...
  • 我們有時候看到一篇好的文章,想去保存下來,傳統方式一般是收藏書簽、複製粘貼到文檔或者直接複製鏈接保存,但這樣一次兩次還好,數量多了,比較麻煩不說,還可能不好找~ 這個時候,Python的作用就來了,直接抓下來導出為PDF,直接把整個網站的內容都導下來都行~ 話不多說,我們直接上代碼! import ...
  • 一個工作了3年的Java程式員,遇到一個Spring Boot的問題。 他對這個問題有一些瞭解,但是回答得不是很好,希望參考我的高手回答。 這個問題是:“如何理解Spring Boot中的Starter”。 對於這個問題,看看普通人和高手的回答。 普通人: 嗯。。。。。。。。。。。。。 高手: St ...
  • 背景: 網上有很多跨域配置,但都存在各種各樣問題;經過改良和測試後,最終形成一個穩定配置版本,我的Spring Boot版本是2.5.1 問題: 前後端分離後,進行聯調,發現瀏覽器出報跨域問題 解決方案: 在config配置文件中添加下麵代碼類。這裡很重要的一點是,在有其他攔截器的時候,通過bean ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...