貪心算法解決活動選擇問題:最多不重疊活動數量求解

題目描述

問題背景

活動選擇問題是貪心算法的經典應用場景之一。假設有若干個活動,每個活動都有獨立的開始時間結束時間,且同一時間只能進行一個活動。要求從這些活動中選擇出最大數量的不重疊活動,即任意兩個選中的活動,前一個活動的結束時間不晚于后一個活動的開始時間。

輸入輸出示例

  • 輸入(開始時間與結束時間分兩行輸入,空格分隔,回車結束):

    plaintext

    1 3 0 5 8 5  // 活動開始時間
    2 4 6 7 9 9  // 活動結束時間
    
  • 輸出

    plaintext

    最大不重疊活動數量: 4
    
  • 解釋:最優選擇為活動?[1,2][3,4][5,7][8,9],共 4 個不重疊活動。

解題思路:貪心算法的核心邏輯

為什么選擇貪心算法?

活動選擇問題的最優解具有 “貪心選擇性質”—— 每次選擇最早結束的活動,能為后續活動預留最多的時間,從而最大化最終選擇的活動數量。這一策略無需回溯,直接通過局部最優選擇即可得到全局最優解。

算法步驟

  1. 數據組織:將每個活動的 “開始時間” 和 “結束時間” 組合成二維向量?vector<vector<int>>,每行代表一個活動(格式:[開始時間, 結束時間])。
  2. 排序:按活動的結束時間升序排序(貪心策略的關鍵,確保優先選擇早結束的活動)。
  3. 篩選不重疊活動
    • 初始選擇第一個活動(最早結束的活動),記錄其結束時間。
    • 遍歷后續活動,若當前活動的 “開始時間 ≥ 上一個選中活動的結束時間”,則選擇該活動,并更新結束時間。
  4. 統計結果:記錄最終選擇的活動數量,即為答案。

完整 C++ 代碼實現

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;/*** @brief 計算最大不重疊活動數量(貪心算法)* @param activities 二維向量,每行存儲一個活動的[開始時間, 結束時間]*/
void selectMaxNonOverlappingActivities(vector<vector<int>>& activities) {// 邊界處理:若沒有活動,直接返回0if (activities.empty()) {cout << "最大不重疊活動數量: 0" << endl;return;}// 按活動結束時間升序排序(貪心算法核心:優先選早結束的活動)sort(activities.begin(), activities.end(), [](const vector<int>& activity1, const vector<int>& activity2) {return activity1[1] < activity2[1]; // 按結束時間從小到大排序});int activityCount = 1;                  // 至少選擇第一個活動int lastActivityEndTime = activities[0][1]; // 記錄上一個選中活動的結束時間// 遍歷剩余活動,篩選不重疊的活動for (size_t i = 1; i < activities.size(); ++i) {// 若當前活動的開始時間 ≥ 上一個活動的結束時間,說明不重疊if (activities[i][0] >= lastActivityEndTime) {activityCount++; // 選擇當前活動lastActivityEndTime = activities[i][1]; // 更新結束時間為當前活動的結束時間}}// 輸出結果cout << "最大不重疊活動數量: " << activityCount << endl;
}int main() {vector<int> startTimes;  // 存儲所有活動的開始時間vector<int> endTimes;    // 存儲所有活動的結束時間vector<vector<int>> activities; // 存儲所有活動([開始時間, 結束時間])int timeInput;           // 臨時存儲輸入的時間值// 讀取活動開始時間(空格分隔,回車結束)cout << "請輸入所有活動的開始時間(空格分隔,回車結束):" << endl;while (cin >> timeInput) {startTimes.push_back(timeInput);// 檢測到回車符,停止讀取開始時間if (cin.peek() == '\n') {cin.ignore(); // 清空輸入緩沖區的換行符,避免影響后續輸入break;}}// 讀取活動結束時間(空格分隔,回車結束)cout << "請輸入所有活動的結束時間(空格分隔,回車結束):" << endl;while (cin >> timeInput) {endTimes.push_back(timeInput);if (cin.peek() == '\n') {break;}}// 輸入合法性校驗:開始時間和結束時間的數量必須一致if (startTimes.size() != endTimes.size()) {cerr << "輸入錯誤:開始時間和結束時間的數量不匹配!" << endl;return 1; // 非0返回值表示程序異常退出}// 組合開始時間和結束時間,構建活動列表for (size_t i = 0; i < startTimes.size(); ++i) {activities.push_back({startTimes[i], endTimes[i]});}// 計算并輸出最大不重疊活動數量selectMaxNonOverlappingActivities(activities);return 0;
}

代碼細節解析

1. 邊界處理與輸入校驗

  • 空活動判斷:若輸入為空(無任何活動),直接輸出 0,避免數組越界。
  • 輸入合法性校驗:確保 “開始時間數量” 與 “結束時間數量” 一致,若不一致則提示錯誤并退出,避免后續邏輯異常。
  • 輸入緩沖區清理:使用?cin.ignore()?清除第一個輸入后的換行符,防止換行符被第二個輸入循環誤讀。

2. 排序邏輯(Lambda 表達式)

cpp

運行

sort(activities.begin(), activities.end(), [](const vector<int>& activity1, const vector<int>& activity2) {return activity1[1] < activity2[1];});

  • 使用 Lambda 表達式作為排序的自定義比較函數,簡潔高效。
  • 按活動的結束時間(activity[1])升序排序,是貪心策略的核心 —— 優先選擇早結束的活動,為后續活動預留更多時間。

3. 活動篩選邏輯

  • 初始選擇第一個活動(排序后最早結束的活動),activityCount?初始化為 1。
  • 遍歷后續活動時,通過?activities[i][0] >= lastActivityEndTime?判斷是否重疊:
    • 若滿足條件:選擇該活動,activityCount?加 1,并更新?lastActivityEndTime?為當前活動的結束時間。
    • 若不滿足:跳過該活動,繼續遍歷下一個。

算法效率分析

時間復雜度空間復雜度說明
O(n log n)O(n)時間復雜度由排序操作主導(sort?函數的時間復雜度為 O (n log n));空間復雜度用于存儲活動列表,為 O (n)(n 為活動數量)。

該效率是活動選擇問題的最優解 —— 貪心算法無需額外的動態規劃數組,在時間和空間上均優于其他解法。

測試用例驗證

測試用例 1:常規輸入(示例輸入)

  • 開始時間:1 3 0 5 8 5
  • 結束時間:2 4 6 7 9 9
  • 排序后活動:[1,2]、[3,4]、[0,6]、[5,7]、[5,9]、[8,9]
  • 選中活動:[1,2]、[3,4]、[5,7]、[8,9]
  • 輸出:4(正確)

測試用例 2:空輸入

  • 開始時間:(直接回車)
  • 結束時間:(直接回車)
  • 輸出:0(正確)

測試用例 3:所有活動重疊

  • 開始時間:1 2 3
  • 結束時間:4 5 6
  • 選中活動:[1,4]
  • 輸出:1(正確)

測試用例 4:活動無重疊

  • 開始時間:1 3 5
  • 結束時間:2 4 6
  • 選中活動:[1,2]、[3,4]、[5,6]
  • 輸出:3(正確)

總結

活動選擇問題是貪心算法的典型應用,核心在于 “優先選擇最早結束的活動” 這一局部最優策略。本文的實現通過清晰的數據組織、嚴格的輸入校驗和高效的排序篩選邏輯,確保了代碼的正確性和可讀性。

該解法不僅適用于經典的活動選擇場景,還可擴展到類似問題(如會議安排、任務調度等),只需將 “活動” 替換為對應的場景實體(如會議、任務),邏輯完全復用。

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

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

相關文章

2025年如何批量下載雪球帖子和文章導出pdf?

之前分享過雪球文章下載 2025 批量下載市場高標解讀/配置喵/wangdizhe 雪球帖子/文章導出excel和pdf 這里以市場高標解讀這個號為例 抓取下載的所有帖子excel數據包含文章日期&#xff0c;文章標題&#xff0c;文章鏈接&#xff0c;文章簡介&#xff0c;點贊數&#xff0c;轉…

【C++】紅黑樹(詳解)

文章目錄上文鏈接一、什么是紅黑樹二、紅黑樹的性質1. 顏色規則2. 紅黑樹的規則為什么可以控制平衡3. 紅黑樹的效率三、紅黑樹的整體結構四、紅黑樹的插入1. 空樹的插入2. 插入節點的父親為黑色3. 插入節點的父親為紅色(1) 叔叔為紅色&#xff1a;變色(2) 叔叔為空或為黑色&…

AI提升SEO關鍵詞效果新策略

內容概要 在2025年&#xff0c;人工智能&#xff08;AI&#xff09;技術正全面革新搜索引擎優化&#xff08;SEO&#xff09;的關鍵詞優化模式。通過智能分析用戶搜索意圖與語義關聯&#xff0c;AI能夠精準匹配關鍵詞并進行高效布局。本文將深入探討AI驅動的關鍵詞策略升級方案…

手動安裝的node到nvm吧版本管理的過程。

前言 本文記錄個人在使用nvm包管理器安裝node 14版本 npm安裝失敗&#xff0c;進行手動安裝的node到nvm吧版本管理的過程。 安裝node 14 時 npm總是安裝失敗&#xff0c;如下圖 通過手動下載對于版本 node下載地址 下載解壓點擊所需的版本下載后解壓 修改解壓后的文件夾名稱…

Python爬蟲實戰:構建Widgets 小組件數據采集和分析系統

1. 引言 1.1 研究背景 在當今數字化時代,Widgets 作為用戶界面的基本組成元素,廣泛應用于移動應用、網站和桌面軟件中,其設計質量直接影響用戶體驗。隨著市場競爭的加劇,了解市場上各類 Widgets 產品的特征、價格區間、用戶評價等信息,對于產品設計和商業決策具有重要價…

1.1 Internet簡介

1.網絡, 計算機網絡, 互聯網 2.不同的角度認識Internet1.網絡, 計算機網絡, 互聯網 網絡表示連接兩點以上的通路系統比如:a.你家到鄰居家的小路 -> 一個小網絡b.一個村子的所有道路 -> 一個更大的網絡c.送外賣的小哥騎車走的路線 -> 一個配送網絡計算機網絡表示專門傳…

pytest使用allure測試報告

&#x1f345; 點擊文末小卡片&#xff0c;免費獲取軟件測試全套資料&#xff0c;資料在手&#xff0c;漲薪更快 選用的項目為Selenium自動化測試Pytest框架實戰&#xff0c;在這個項目的基礎上說allure報告。 allure安裝 首先安裝python的allure-pytest包 pip install allu…

PortSwigger靶場之SQL injection with filter bypass via XML encoding通關秘籍

一、題目分析該實驗室的庫存查詢功能存在 SQL 注入漏洞。查詢結果為這些信息會出現在應用程序的響應中&#xff0c;因此您可以利用“聯合”攻擊來從其他表中獲取數據。該數據庫中有一個“用戶”表&#xff0c;該表包含了已注冊用戶的用戶名和密碼。要解決&#xff0c;需進行一次…

Cocos游戲中自定義按鈕組件(BtnEventComponent)的詳細分析與實現

概述在Cocos游戲開發中&#xff0c;按鈕交互是用戶界面中最基礎且重要的組成部分。原生的Cocos Button組件雖然功能完善&#xff0c;但在復雜的游戲場景中往往無法滿足多樣化的交互需求。本文將詳細分析一個功能強大的按鈕組件BtnEventComponent&#xff0c;它提供了多種交互模…

終于完成William F. Egan所著的Practical RF System Design的中文版學習資料

終于完成William F. Egan所著的Practical RF System Design的中文版學習資料 該文檔聚焦RF系統的分析與設計。書中先介紹系統設計流程、書籍結構及工具&#xff08;如電子表格、測試與仿真&#xff09;&#xff0c;接著圍繞RF系統關鍵參數展開&#xff1a;講解增益計算&#xf…

嵌入式Linux驅動開發:蜂鳴器驅動

嵌入式Linux驅動開發&#xff1a;蜂鳴器驅動 1. 引言 本文檔詳細記錄了基于i.MX6ULL處理器的蜂鳴器驅動開發過程。內容涵蓋驅動的理論基礎、代碼實現、設備樹配置以及用戶空間應用程序的編寫。本文檔嚴格遵循用戶提供的代碼和文檔&#xff0c;確保理論與實踐的緊密結合。本文檔…

Qt中的鎖和條件變量和信號量

Qt中的鎖和條件變量和信號量 C11中引入智能指針用來解決鎖忘記釋放的問題 代碼如下&#xff1a; void Thread::run() {for(int i0;i<50000;i){QMutexLocker locker(&mutex);//mutex.lock();num;//mutex.unlock();} }大括號結束的時候&#xff0c;生命周期踩結束&#xf…

智能電視MaxHub恢復系統

公司的MaxHub智能電視又出故障了。 去年硬件故障返廠&#xff0c;花了8600多元。 這次看上去是軟件故障。開機后藍屏報錯。 按回車鍵&#xff0c;電視重啟。 反復折騰幾次&#xff0c;自行修復執行完畢&#xff0c;終于可以進入系統了。 只不過進入windows10后&#xff0c;圖…

TensorFlow 面試題及詳細答案 120道(71-80)-- 性能優化與調試

《前后端面試題》專欄集合了前后端各個知識模塊的面試題,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。 前后端面試題-專欄總目錄 文章目錄 一、本文面試題目錄 71. 如何優化TensorFlow模…

數據結構 第三輪

以看嚴蔚敏老師的教材為主&#xff0c;輔以其他輔導書&#xff1a;王道&#xff0c;新編數據結構&#xff0c;學校講義 線性結構&#xff1a;線性表、串、隊列、棧、數組和廣義表 樹形結構、網狀結構&#xff1a;圖 查找、排序 動態內存管理和文件 緒論 8-29 數據&#xf…

[新啟航]新啟航激光頻率梳 “光量子透視”:2μm 精度破除遮擋,完成 130mm 深孔 3D 建模

摘要&#xff1a;本文介紹新啟航激光頻率梳的 “光量子透視” 技術&#xff0c;該技術憑借獨特的光量子特性與測量原理&#xff0c;以 2μm 精度破除深孔遮擋&#xff0c;成功完成 130mm 深孔的 3D 建模&#xff0c;為深孔三維形態的精確獲取提供了創新解決方案&#xff0c;推動…

MongoDB /redis/mysql 界面化的數據查看頁面App

MongoDB、Redis 和 MySQL 都有界面化的數據查看工具&#xff0c;以下是相關介紹&#xff1a; MongoDB 輸入MongoDB的賬號密碼即可讀取數據&#xff0c;可訪問數據。 MongoDB Compass&#xff1a;這是 MongoDB 官方提供的 GUI 管理工具&#xff0c;支持 Windows、Mac 和 Linux 等…

Spring Boot 實戰:接入 DeepSeek API 實現問卷文本優化

本文結合 Spring Boot 項目&#xff0c;介紹如何接入 DeepSeek API&#xff0c;自動優化問卷文本&#xff0c;并給出完整示例代碼及詳細注釋。一、項目目標 目標是實現一個 REST 接口&#xff0c;將原始問卷文本提交給 DeepSeek API&#xff0c;然后返回優化后的文本給前端。 接…

opencv實現輪廓繪制和選擇

前面學習了opencv中圖像的一些處理&#xff0c;但對于opencv我們更多的還是對圖像做出一些判斷和識別&#xff0c;所以下面開始學習圖像的識別。 原圖&#xff1a; 一 圖像輪廓的識別 import cv2 pencv2.imread(pen.png,0) ret,new_pencv2.threshold(pen,120,255,cv2.THRESH_…

【Linux】Docker洞察:掌握docker inspect命令與Go模板技巧

&#x1f468;?&#x1f393;博主簡介 &#x1f3c5;CSDN博客專家 ??&#x1f3c5;云計算領域優質創作者 ??&#x1f3c5;華為云開發者社區專家博主 ??&#x1f3c5;阿里云開發者社區專家博主 &#x1f48a;交流社區&#xff1a;運維交流社區 歡迎大家的加入&#xff01…