【信奧一本通提高篇】基礎算法之貪心算法

原文

https://bbs.fmcraft.top/blog/index.php/archives/22/

貪心算法

概述

近年來的信息學競賽試題,經常出現求一個問題的可行解或最優解的題目。這類問題就是我們通常所說的最優化問題。貪心算法是求解這類問題的一種常用算法。在眾多的算法中,貪心算法可以算得上是最接近人們日常思維的一種算法,常被信息學奧賽選手用來求解一些數據規模很大的問題。

一、貪心算法

貪心算法是從問題的初始狀態出發,通過若干次的貪心選擇而得到的最優值(或較優值)的一種求解問題策略,即貪心策略。
換句話說,貪心策略是一種在每次決策時采取當前意義下最優策略的算法,做出的選擇只是在某種約束條件下的局部最優解或較優解,并不一定是全局的最優解或較優解。不過,某些特定的問題是可以利用貪心算法求得其最優解或較優解的。
【引例1】在N行M列的正整數矩陣中,要求從每行中選出一個數,使得選出的N個數的和最大。
分析:本題可以用貪心算法求解。選N次,每一次選出相應行中的最大值即可。
【引例2】在一個N×M的方格陣中,每一格子賦予一個數(即權值),規定每次移動時只能向上或向右。現試找出一條路徑,使其從左下角至右上角所經過的權值之和最大。
我們以2×3的矩陣為例:

/列1列2列3
行1346
行21210
若按貪心算法求解,所得路徑為:1→3→4→6。
若按動態規劃求解,所得路徑為:1→2→ 10→6。
顯然,這里用貪心算法求解,得到的并不是問題的最優解。

二、貪心算法的特點

1.貪心選擇

所謂貪心選擇是指應用同一規則,將原問題變為一個相似的但規模更小的子問題,而后的每 一步都是當前看似最佳的選擇,且這種選擇只依賴于已做出的選擇,不依賴于未做出的選擇。

最優子結構

執行算法時,每一次得到的結果雖然都是當前問題的最優解(即局部最優解),但只有滿足全 局最優解包含局部最優解時,才能保證最終得到的結果是最優解。

三、幾個簡單的貪心實例

1.最優裝載問題

給 n 個物體,第i個物體重量為W?, 選擇盡量多的物體,使得總重量不超過C。
【思路點撥】
由于只關心物體的數量,所以裝重的沒有裝輕的劃算。只需把所有物體按重量從小到大排 序,依次選擇每個物體,直到裝不下為止。這就是一種典型的貪心算法,它只顧眼前,但卻能得到全 局最優解。
貪心策略:先裝最輕的。

2.部分背包問題

有n 個物體,第i個物體的重量為w?, 價值為 v?,在總重量不超過C 的情況下讓總價值盡量高。 每一個物體可以只取走一部分,價值和重量按比例計算。
【思路點撥】
本題是在上一題的基礎上增加了價值項,所以不能簡單地像上一題那樣先選出輕的(輕的可 能其價值也小),也不能先拿價值大的(它可能特別重),而應該綜合考慮兩個因素。一種直觀的貪心策略是:優先選出價值與重量的比值最大的,直到重量和正好為C。
注意:由于每個物體可以只選出一部分,因此一定可以讓總重量恰好為C(或者所有物體全選,總重量還不足C), 而且除了最后一個以外,所有的物體要么不選,要么全部選。
貪心策略:先選出性價比高的。

3.乘船問題

有n個人,第i個人重量為w,。每艘船的載重量均為C,最多可乘兩個人。求用最少的船裝載所有人的方案。
【思路點撥】
考慮最輕的人i, 他應該和誰一起乘呢?如果每個人都不能和他一起乘,則只能每人乘一艘船。 否則,他應該選擇能和他一起乘的人中最重的一個人j。這樣的選擇只是讓“眼前”的浪費最少,因此它是一種貪心策略。
貪心策略:最輕的人和最重的人配對。
這個貪心策略的正確性和有效性是可以用反證法證明的。
證明:假設這個貪心策略不是最優的,最優方案中的i是什么樣的呢?
情況1:i不和任何一個人乘同一艘船,那么可以把j拉過來和他一起乘,總船數不會增加(且可能會減少!),并且符合貪心策略。
情況2:i和另外一個人k同乘一艘船,其中k比j輕。把j和k交換后,j原來所在的船仍然不會超重(因為k比j輕),因此i和j同乘一艘船,所得到的新解不會更差,且符合貪心策略。
由此可見,利用本題的貪心策略求解不會丟失最優解。
程序實現。在前面的分析中,比j更重的人只能每人乘一艘船。這樣,我們只需用兩個指針i和j分別表示當前考慮的最輕的人和最重的人。每次先將指針j往左移動,直到i和j可以共乘一艘船,然后將指針i往右移,指針j往左移,并重復上述操作,直到所有的人都裝載上。不難看出,這 個程序的時間復雜度僅為O(n), 是最優算法。

總結

通過以上3個例子,我們大致了解了貪心算法的形式和正確性證明的基本方法。下面,進一步分析幾個經典貪心算法的應用,加深對貪心算法的理解。

四、貪心算法的經典應用

1.選擇不相交區間問題

給定n個開區間(a,b),選擇盡量多個區間,使得這些區間兩兩沒有公共點。
【思路點撥】
首先,按照b_1<=b_2<=…<=b_n,的順序排序,依次考慮各個區間,如果沒有和已經選擇的區間沖突,就選:否則就不選。
【正確性】
假設b_1<b_i且(a_j,b_j)、(a_i,b_i) 分別與之前的區間不沖突,當前選(a_j,b_j).若(a_j,b_j)與(a_j,b_i)不沖突,則還可以選擇(a_i,b_i),答案個數加一;若(a_j,b_j)與(a_i,b_i)沖突,因為b_j<b_i,所以選(a_j,b_j)對以后的影響更小。

2.區間選點問題

【問題描述】
給定n個閉區間[a_i,b_i], 在數軸上選盡量少的點,使得每個區間內都至少有一個點(不同區同內含的點可以是同一個)。
【思路點撥】
首先按照區間的結束位置從小到大排序。然后從區間1到區間n 進行選擇:對于當前區間,吾 集合中的數不能覆蓋它,則將區間末尾的數加入集合。
貪心策略:取最后一個。
如圖下圖所示,如果選灰色點,則移動到黑色點會更優。
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

3.區間覆蓋問題

【問題描述】
給n個閉區間[a_i,b_i],選擇盡量少的區間覆蓋一條指定的線段區間[s,t]。
【思路點撥】
將所有的區間按左端點從小到大排序,依次處理每個區間。每次選擇覆蓋點s的區間中右端 點坐標最大的一個,并將s更新為該區間的右端點坐標,直到選擇的區間已包含了t為止。
貪心策略:在某個時刻的s, 找一個滿足a[i]≤s的b[i]最大值即可。

4.流水作業調度問題

【問題描述】
有n個作業要在兩臺機器M1和M2組成的流水線上完成加工。每個作業i都必須先花時間a在M上加工,然后花時間b在M2上加工。
確定n個作業的加工順序,使得從作業1在機器M1上加工開始到作業n在機器M2上加工實完為止所用的總時間最短。
【思路點撥】
直觀上,最優調度一定讓M1、M2的空閑時間盡量短。
Johnson算法:設N1為a<b的作業集合,N2 為a≥b的作業集合,將N1的作業按a非減序排序,N2中的作業按照b非增序排序,則N1作 業接N2作業構成最優順序。
算法的程序易于實現,時間復雜度為O(nlogn),正確性需要證明。

5.帶限期和罰款的單位時間任務調度

【問題描述】
有n個任務,每個任務都需要1個時間單位執行,任務i的截止時間d_i(1≤d≤n)表示要求任務i在時問d_i結束時必須完成,誤時懲罰w_i表示若任務i未在時間d_i結束之前完成,將導致w_i的罰款。
確定所有任務的執行順序,使得懲罰最少。
【思路點撥】
要使罰款最少.我們顯然應盡量完成w[i]值較大的任務。
此時,我們可以將任務按w[i]從大到小進行排序,然后按照排好的順序依次對任務進行安排。 安排的規則為:使處理任務i的時間既在d[i]之內,又盡量靠后;如果d[i]之內的時間都已經排滿,就放棄處理此項任務。
【算法證明】
假設按照上述算法得到的解不是最優的,那么必然存在某個任務j應當安排到處理的過程中 但卻沒有安排。假設我們要將該任務安排進去,由于在時間d[j]內都已經排滿,就必然需要將一個已安排的任務k與之替換,而w[k]≥w[j]。 這樣,替換顯然會增加罰款的數額、因此,除上還安排方法以外的安排方法都不會使罰款的數額減少,可知用上述算法得到的結果是最優的。
【實現方法】
①先按照罰款數額從大到小快排。
②順序處理每個任務,若能安排,則找一個最晚時間:否則放在最后的空位上。

練習

如需練習學習的內容,可自行尋找相關題目。
也可以前往FMCRAFT OJ做題。下面的地址可以直接跳轉到其相關題目一本通訓練中的題單 算法訓練中的題單。使用OJ前需要注冊賬戶。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/74057.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74057.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74057.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CentOS-7.0系統基礎操作

配置ip地址 編輯網卡文件&#xff1a; vi etc/sysconfig/network-scripts/ifcfg-ens33 在網卡文件里參照如下設置&#xff1a; BOOTPROTO"static" IPADDR192.168.61.233 GATEWAY192.168.61.2 NETMASK255.255.255.0 ONBOOT"yes" 防火墻管理 開啟防火墻&am…

【大模型應用】信息抽取的調研

老規矩&#xff0c;先占坑&#xff0c;后續更新。 關鍵詞&#xff1a; Pydantic functioncal 參考文獻&#xff1a;小白學大模型&#xff1a;自定義信息抽取Agent-CSDN博客

MySQL內存使用率高問題排查與解決方案:

目錄標題 **一、問題現象****二、核心排查步驟****1. 參數檢查****2. 內存使用分析****3. 存儲過程/函數/視圖檢查****4. 操作系統級檢查** **三、解決方案****1. 調整MySQL配置****2. 關閉透明大頁&#xff08;THP&#xff09;****3. 優化查詢與存儲過程****4. 硬件與環境優化…

華為GaussDB數據庫的手動備份與還原操作介紹

數據庫的備份以A機上的操作為例。 1、使用linux的root用戶登錄到GaussDB服務器。 2、用以下命令切換到 GaussDB 管理員用戶&#xff0c;其中&#xff0c;omm 為當前數據庫的linux賬號。 su - omm 3、執行gs_dump命令進行數據庫備份&#xff1a; 這里使用gs_dump命令進行備…

How to install OpenJ9 JDK 17 on Ubuntu 24.04

概述 OpenJ9 是一款由 IBM 開發并開源的 Java 虛擬機&#xff08;JVM&#xff09;&#xff0c;現由 ?Eclipse 基金會管理&#xff08;名為 ?Eclipse OpenJ9&#xff09;。它旨在提供高性能、低內存消耗和快速啟動時間&#xff0c;特別適用于云原生和容器化環境。 關鍵特性 …

洛谷題單1-P5705 【深基2.例7】數字反轉-python-流程圖重構

題目描述 輸入一個不小于 100 100 100 且小于 1000 1000 1000&#xff0c;同時包括小數點后一位的一個浮點數&#xff0c;例如 123.4 123.4 123.4 &#xff0c;要求把這個數字翻轉過來&#xff0c;變成 4.321 4.321 4.321 并輸出。 輸入格式 一行一個浮點數 輸出格式 …

【云服務器】在Linux CentOS 7上快速搭建我的世界 Minecraft 服務器搭建,并實現遠程聯機,詳細教程

【云服務器】在Linux CentOS 7上快速搭建我的世界 Minecraft 服務器搭建&#xff0c;詳細詳細教程 一、 服務器介紹二、下載 Minecraft 服務端三、安裝 JDK 21四、搭建服務器五、本地測試連接六、添加服務&#xff0c;并設置開機自啟動 前言&#xff1a; 推薦使用云服務器部署&…

內網穿透_ZeroTiers部署_廣和通SC171_aidlux_嵌入式

下載 sudo curl -s https://install.zerotier.com | sudo bash &#xff08;需要科學上網&#xff09; 所有涉及硬件的操作好像都需要 root 權限&#xff0c;curl 在這里需要連接網絡&#xff0c;所以也需要 sudo sudo zerotier-cli status 若返回 200 info 及設備 ID&#xff…

Faster RCNN Pytorch 實現 代碼級 詳解

基本結構&#xff1a; 采用VGG提取特征的Faster RCNN. self.backbone:提取出特征圖->features self.rpn:選出推薦框->proposals self.roi heads:根據proposals在features上進行摳圖->detections features self.backbone(images.tensors)proposals, proposal_losses…

【Matlab】-- 基于MATLAB的美賽常用多種算法

文章目錄 文章目錄 01 內容概要02 各種算法基本原理03 部分代碼04 代碼下載 01 內容概要 本資料集合了多種數學建模和優化算法的常用代碼資源&#xff0c;旨在為參與美國大學生數學建模競賽&#xff08;MCM/ICM&#xff0c;簡稱美賽&#xff09;的參賽者提供實用的編程工具和…

Vue2和Vue3響應式的基本實現

目錄 簡介Vue2 響應式Vue2 響應式的局限性 Vue3 響應式Vue3 響應式的優點 Vue2 和 Vue3 響應式對比 簡介 在 Vue 框架中&#xff0c;數據的響應式是其核心特性之一。當頁面數據發生變化時&#xff0c;我們希望界面能自動更新&#xff0c;而不是手動操作 DOM。這就需要對數據進…

Linux系統中快速安裝docker

1 查看是否安裝docker 要檢查Ubuntu是否安裝了Docker&#xff0c;可以使用以下幾種方法&#xff1a; 方法1&#xff1a;使用 docker --version 命令 docker --version如果Docker已安裝&#xff0c;輸出會顯示Docker的版本信息&#xff0c;例如&#xff1a; Docker version …

ElasticSearch 分詞器

文章目錄 一、安裝中文分詞插件Linux安裝7.14.1版本&#xff1a;測試1&#xff1a;ik_smart測試2&#xff1a;ik_max_word 二、es內置的分詞器&#xff1a;三、拼音插件安裝以及&#xff08;IKpinyin使用&#xff09;配置 IK pinyin 分詞配置 一、安裝中文分詞插件 IK Analys…

arm64位FFmpeg與X264庫

參考鏈接&#xff1a; https://blog.csdn.net/gitblog_09700/article/details/142945092

機器學習與深度學習4:數據集處理Dataset,DataLoader,batch_size

深度學習中&#xff0c;我們能看到別人的代碼中都有一個繼承Dataset類的數據集處理過程&#xff0c;這也是深度學習處理數據集的的基礎&#xff0c;下面介紹這個數據集的定義和使用&#xff1a; 1、數據集加載 1.1 通用的定義 Bach&#xff1a;表示每次喂給模型的數據 Epoc…

MySQL數據庫和表的操作之SQL語句

&#x1f3af; 本文專欄&#xff1a;MySQL深入淺出 &#x1f680; 作者主頁&#xff1a;小度愛學習 MySQL數據庫和表的操作 關系型數據庫&#xff0c;都是遵循SQL語法進行數據查詢和管理的。 SQL語句 什么是sql SQL&#xff1a;結構化查詢語言(Structured Query Language)&…

ubuntu開發mcu環境

# 編輯 vim或者vscode # 編譯 arm-none-eabi # 燒寫 openocd 若是默認安裝&#xff0c;會在/usr/share/openocd/scripts/{interface,target} 有配置接口和目標版配置 示例&#xff1a; openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg 啟動后&#xff0c;會…

Windows模仿Mac大小寫切換, 中英文切換

CapsLock 功能優化腳本部署指南 部署步驟 第一步&#xff1a;安裝 AutoHotkey v2 訪問 AutoHotkey v2 官網下載并安裝最新版本安裝時勾選 "Add Compile Script to context menus" 第二步&#xff1a;部署腳本 直接運行 (調試推薦) 新建文本文件&#xff0c;粘貼…

Selenium Web自動化如何快速又準確的定位元素路徑,強調一遍是元素路徑

如果文章對你有用&#xff0c;請給個贊&#xff01; 匹配的ChromeDriver和瀏覽器版本是更好完成自動化的基礎&#xff0c;可以從這里去下載驅動程序&#xff1a; 最全ChromeDriver下載含win linux mac 最新版本134.0.6998.165 持續更新..._chromedriver 134-CSDN博客 如果你問…

CSRF vs SSRF詳解

一、CSRF&#xff08;跨站請求偽造&#xff09;攻擊全解 攻擊原理示意圖 受害者瀏覽器 ├── 已登錄銀行網站&#xff08;Cookie存活&#xff09; └── 訪問惡意網站執行&#xff1a;<img src"http://bank.com/transfer?tohacker&amount1000000">核心…