二.常見算法--貪心算法

(1)單源點最短路徑問題

問題描述:

給定一個圖,任取其中一個節點為固定的起點,求從起點到任意節點的最短路徑距離。

例如:

思路與關鍵點:

以下代碼中涉及到宏INT_MAX,存在于<limits.h>中。

首先,建立三個數組dist,S,W,prev分別用來存儲從起始節點到任意節點的最短距離相對于s距離起點的最短路徑節點集合存儲要遍歷的圖的各條邊的距離;用來存儲各個節點的直接前驅節點。

3個主要的個功能函數。

(1)minDistance函數用來尋找V-S集合中的距離起點的最短距離,并返回該節點的下標。

(2)dijkstra函數用來尋找從起始節點到任意節點的最短路徑長度。

思路是把節點分為兩類,一類是沒有放進S集合中的節點,一類是已經放進去的節點。那么,尋找從起始節點到節點v的最短路徑就有兩種可能的取值。

第一種是組成該最短路徑的就是dist[v]。

第二種是新加入S集合的節點u可能會組成一個新的更短的路徑,這時,要更新dist[v]。

(3)Traceback函數用來打印從源點到終點的路徑。這個函數基于prev數組,該數組建立的核心原理是:每次更新dist數組,一定是因為s集合中增加了一個節點u,這個u一定是當前更新dist[v]的直接前驅節點。遞歸調用,不斷找前一個前驅節點,就可以打印出完整路徑了。

偽代碼:

代碼:

#include <iostream>
#include <limits.h>using namespace std;
#define V 6  // 節點的數量void Traceback(int v, int i, int prev[]);int minDistance(int dist[], int S[]);void printSolution(int dist[]);void dijkstra(int W[V][V], int src);int main() {int W[V][V] = {{0, 3, 2, 0, 0, 0},{0, 0, 0, 0, 1, 0},{0, 0, 0, 8, 4, 0},{0, 0, 0, 0, 0, 1},{0, 0, 0, 5, 0, 0},{0, 0, 0, 0, 0, 0}};dijkstra(W, 0);//起始節點為節點 0 return 0;}
// 找到距離數組中最小值的索引
int minDistance(int dist[], int S[]) {int min = INT_MAX, min_index;for (int j = 0; j < V; j++) {/*如果節點j沒有包含在最短路徑數組中,初始時,只要有路徑,就更新最短路徑數組的值。后面,每次進入循環都與當前的最短距離進行比較,更新。找到V(全部節點集合)-S(已找到的最短路徑節點集合)中距離起點最短的路徑的節點編號。 */ if (S[j] == 0 && dist[j] <= min) {min = dist[j];min_index = j;}}return min_index;
}// 打印最終的最短路徑
void printSolution(int dist[]) {printf("節點\t最短距離\n");for (int i = 0; i < V; i++)printf("%d\t%d\n", i, dist[i]);
}// Dijkstra算法的實現
void dijkstra(int W[V][V], int src) {int dist[V];     // 存儲從源節點到每個節點的最短距離int S[V];   // 記錄節點是否已經包含在已找到的最短路徑節點集合中int prev[V];// 初始化所有距離為無窮大,標記所有節點為未包含for (int i = 0; i < V; i++) {dist[i] = INT_MAX;S[i] = 0;}// 設置起始節點的距離為0dist[src] = 0;// 找到最短路徑for (int count = 0; count < V - 1; count++) {// 選擇距離最小的節點int u = minDistance(dist, S);// 標記節點為已包含S[u] = 1;// 更新相鄰節點的距離for (int v = 0; v < V; v++) {/*如果該節點沒有包含在最短路徑數組中,有路徑可直接到達該節點,并且有路徑可達該節點,并且,從節點0到節點u的最短路徑長度,與,從節點u到節點v的路徑距離之和小于從節點0到該節點當前最短距離,則更新最短距離。 */ if (!S[v] &&W[u][v] && dist[u] != INT_MAX &&dist[u] +W[u][v] < dist[v]) {dist[v] = dist[u] + W[u][v];prev[v]=u;}}}// 打印最終的最短路徑printSolution(dist);int v,i;printf("請輸入源點及終點");cin>>v>>i;printf("從源點%d到終點%d的最短路徑為:\n",v,i);Traceback(v,i,prev);
}
//輸出最短路徑 v源點,i終點,
void Traceback(int v, int i, int prev[])
{// 源點等于終點時,即找出全部路徑if (v == i){cout << i;return;}Traceback(v, prev[i], prev);cout << "->" << i;
}

運行結果:

關鍵步驟證明:

時間復雜度與空間復雜度:

時間復雜度為0(n^{2}),空間復雜度為0(n^{2})。

(2)活動選擇問題

問題描述:

假定有一個n個活動的集合S={a1,a2,……,an},這些活動使用同一個資源,而這個資源在某個時刻只能供一個活動使用。每個活動有一個開始時間si和一個結束時間fi,其中0<=si<fi<∞。如果被選中,任務ai發生在半開時間區間[si,fi)期間。如果兩個活動ai和aj滿足[si,fi)和[sj,fj)不重疊,則稱他們是兼容的.也就是說,若si>=fj或sj>=fi,則ai和aj是兼容的。

在活動選擇問題中,我們希望選出一個最大兼容活動集。

例子:

該活動序列的最大兼容活動集為1,4,8或1,4,9

思路與關鍵點:

按活動結束時間從小到大排序

每次選擇的活動將作為是否與下一個活動兼容的判斷依據。

偽代碼:

代碼:

#include<iostream>
#include<string.h>
using namespace std;
void Traceback(int Trace[],int n);
void sort(int n,int *s,int* f)
{int a,b,i,j;//冒泡排序,按結束時間從小到大排列活動 for(i=1;i<n;i++){for(j=1;j<n-i+1;j++){if(f[j]>f[j+1]){a=f[j];f[j]=f[j+1];f[j+1]=a;b=s[j];s[j]=s[j+1];s[j+1]=b;}}} 
}
int GreedySelect(int n,int s[],int f[],bool A[])
{int Trace[n];Trace[1]=1;A[1]=true;//第一個活動必然在最優解中 int j=1,count=1; //從第二個活動開始,尋找下一個兼容的活動 for(int i=2;i<=n;i++){if(s[i]>=f[j]){A[i]=true;j=i;//將已經選人的最后一個活動標號作為下一次比較兼容的參照 count++;Trace[count]=i;}else A[i]=false;} Traceback(Trace,count);return count;
}
//打印的活動序列是按照結束時間從小到大排好序的活動序列,而不是原來的活動序列 void Traceback(int Trace[],int n){printf("活動安排順序為:");for(int i=1;i<=n;i++){cout<<"->"<<Trace[i];}cout<<endl;}
int main(){int n,s[50],f[50];bool A[50];memset(A,false,sizeof(A)); printf("請輸入活動個數:\n"); cin>>n;//活動標號與數組下標保持一致,從1開始標號 for(int i=1;i<=n;i++){printf("請輸入第%d個活動的開始時間和結束時間\n",i);cin>>s[i]>>f[i];printf("第%d個活動的開始時間是%d,結束時間是%d\n",i,s[i],f[i]);} sort(n,s,f);printf("最多相容活動數為:\n");cout<<GreedySelect(n,s,f,A)<<endl;return 0;
}

運行結果:

關鍵步驟證明:

時間復雜度與空間復雜度:

時間復雜度主要為排序花的時間為0(n^{2}),如果換成其他排序可以降低時間復雜度,空間復雜度為0(n)

(3)最小生成樹--prim算法實現

問題描述:

給定一個圖,求出其最小生成樹

最小生成樹定義
? ? 對于一個帶權(假定每條邊上的權值均為大于零的實數)連通無向圖G中的不同生成樹,各樹的邊上的權值之和可能不同;圖中所有生成樹中具有邊上的權值之和最小的樹稱為該圖的最小生成樹.

? ? 按照生成樹的定義,n個頂點的連通圖的生成樹有n個頂點和(n-1)條邊.因此構造最小生成樹的準則有三條:
(1) 必須只使用該圖中的邊來構造最小生成樹;
(2) 必須使用且僅使用(n-1)條邊來連接圖中的n個頂點;
(3) 不能使用產生回路的邊.

思路與關鍵點:

首先,這里有一個頭文件<alogrithmn>,里面包含了豐富實用的函數,非常nice。這里使用到了其中的fill函數和min函數。分別用來填充數組和求最小值的。建立一個數組used,記錄哪些沒有進入最小生成樹的集合,每次不斷地將沒有加入used中的距離加入used數組的節點?權值最小的節點加入used數組。?更新V輪mincost數組,得到最小生成樹。

偽代碼:

代碼:

#include<iostream>
#include<algorithm>
#define MAX_V 100
#define INF 1000 
using namespace std;  int main()
{int V,E;int i,j,m,n;int cost[MAX_V][MAX_V];//存儲每個節點之間的權值 int mincost[MAX_V];//記錄那些已經進入最小生成樹的節點之間的權值 bool used[MAX_V];//用于判斷是否已經進入最小生成樹,false表示否,true表示是 printf("請輸入節點個數與邊數\n"); cin>>V>>E;int Trace[V];fill(mincost,mincost+V+1,INF);//最小生成樹一共有V個節點,V+1條邊 fill(used,used+V,false);//一共有V個節點 //初始化cost[] for(i=0;i<V;i++){for(j=0;j<V;j++){if(i==j) cost[i][j]=0;//節點自己到自己權值為0 else cost[i][j]=INF; }}//向cost[]里面填充各個節點之間的權值 for(m=0;m<E;m++){printf("請輸入兩個端點以及它們之間邊的權值\n");cin>>i>>j>>cost[i][j];cost[j][i]=cost[i][j];//無向圖,中心對稱 }mincost[0]=0; int res=0;//存儲最終的最小生成樹權值和 int count=0;/*遍歷圖,不斷地將沒有加入used中的距離加入used數組的節點權值最小的節點加入used數組。 
更新V輪mincost數組,得到最小生成樹。 */while(true)//也可以寫成for(int i=0;i<V;i++) {int v=V;for(m=0;m<V;m++){	if((!used[m])&&(mincost[m]<mincost[v]))v=m; }Trace[count]=v;count++;	if(v==V) break;Trace[count]=v;//最后一個跳出來了,沒記錄,要把最后一個節點加入 used[v]=true;res+=mincost[v];for(m=0;m<V;m++){/*取(新加入最小生成樹的節點到其他節點的權值)和記錄在mincost中的到其他節點的權值進行比較,取它們之間的最小值,來更新mincost數組*/ mincost[m]=min(mincost[m],cost[v][m]);  }}printf("最小生成樹權值是:\n");cout<<res<<endl;printf("依次找到的節點是:\n");for(int i=0;i<V;i++){cout<<"->"<<Trace[i];}cout<<endl; 
}

運行結果:

輸入上面單源點最短路徑所示的圖,運行結果如下

關鍵步驟證明:

視頻證明

時間復雜度與空間復雜度:

時間復雜度與空間復雜度都是0(_n{2})

友情鏈接:貪心算法

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

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

相關文章

python+selenium - UI自動框架之封裝查找元素

單一的元素定位方法不能滿足所有元素的定位&#xff0c;可以根據每個元素的特點來找到合適的方法&#xff0c;可以參考下圖的方法&#xff1a; elementFind.py from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_con…

Vue filter實戰詳解

在 Vue.js 中&#xff0c;filter 是一種用于在模板中對數據進行格式化的功能。它可以用來對數據進行處理、過濾或格式化&#xff0c;然后在模板中直接使用。 filter 是一種全局的 Vue 實例方法&#xff0c;可以在任何組件的模板中使用。 1.定義全局過濾器&#xff1a; 在 Vue…

InnoDB如何解決幻讀的

InnoDB 使用一種稱為 Next-Key Locking 的鎖機制來解決幻讀問題。幻讀發生在一個事務在讀取某個范圍內的記錄時&#xff0c;另一個事務在這個范圍內插入新的記錄。InnoDB 的 Next-Key Locking 結合了行鎖&#xff08;Row Lock&#xff09;和間隙鎖&#xff08;Gap Lock&#xf…

MavLinK協議

由于在公司需要使用這個&#xff0c;我就寫一個文章用于入門級別 簡單介紹 MAVSDK是PX4開源團隊貢獻的基于mavlink通信協議的用于無人機應用開發的SDK&#xff0c;其可以部署在Windows、Linux、Android等多種平臺&#xff0c;并且支持多種語言如c/c、python、Java等。 在官網…

GIS讀研與求職準備:GNSS專業研0

本文介紹GIS方向研究生入學初期&#xff0c;為將來轉碼、從事開發類工作所作求職準備的規劃路徑、方向選擇等方面的建議。 最近&#xff0c;有很多師弟師妹詢問關于研究生方向選擇、求職準備、就業方向選擇等方面的問題。首先非常感謝大家的盲目信任&#xff08;開個玩笑&#…

基于 debian 12 利用 kubeadm 部署 k8s 1.29 版本

基于 debian 12 利用 kubeadm 部署 k8s 1.29 版本 預先準備 準備三臺debian 12的虛擬機&#xff0c;配置如下&#xff1a; HostnameIP配置k8s-master1192.168.31.604vCPU、8GiB 內存、50GiB 硬盤k8s-worker1192.168.31.614vCPU、8GiB 內存、50GiB 硬盤k8s-worker2192.168.31.6…

python從0開始學習(九)

前言 上一篇文章我們介紹了python中的序列類型和元組類型&#xff0c;本篇文章將接著往下將。 1、字典類型 字典類型是根據一個信息查找另一個信息的方式所構成的“鍵值對”&#xff0c;它表示索引用的鍵和對應的值構成的成對關系。它是一個可變數據類型&#xff0c;也就是說它…

Leetcode 3154. Find Number of Ways to Reach the K-th Stair

Leetcode 3154. Find Number of Ways to Reach the K-th Stair 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3154. Find Number of Ways to Reach the K-th Stair 1. 解題思路 這一題思路上就是一個動態規劃&#xff0c;我們只需要確定一下運行的終止條件&#xff0c;然后寫…

React中顯示數據

SX 會讓你把標簽放到 JavaScript 中。而大括號會讓你 “回到” JavaScript 中&#xff0c;這樣你就可以從你的代碼中嵌入一些變量并展示給用戶。例如&#xff0c;這將顯示 user.name&#xff1a; return (<h1>{user.name}</h1> ); 你還可以將 JSX 屬性 “轉義到 …

《web應用技術》第9次課后作業

一、將前面的代碼繼續完善功能 1、采用XML映射文件的形式來映射sql語句&#xff1b; 2、采用動態sql語句的方式&#xff0c;實現條件查詢的分頁。 二、學習git的使用。 1、每個小組將自己的項目上傳到gitee&#xff0c;學會協作開發&#xff1b; 2、學會從gitee上拉取項目…

【Text2SQL 經典模型】TypeSQL

論文&#xff1a;TypeSQL: Knowledge-Based Type-Aware Neural Text-to-SQL Generation ??? Code: TypeSQL | GitHub 一、論文速讀 本論文是在 SQLNet 網絡上做的改進&#xff0c;其思路也是先預先構建一個 SQL sketch&#xff0c;然后再填充 slots 從而生成 SQL。 論文發…

C++函數指針,鍵值對集合的學習

這段代碼使用了 std::unordered_map 來存儲 std::wstring 作為鍵&#xff08;key&#xff09;&#xff0c;而對應的值&#xff08;value&#xff09;是一個 std::function<void(std::array<int, 5>, SomeClass&, int)> 類型的函數指針。這個結構使得根據字符串…

C++ 時間處理-日期時間類

1. 關鍵詞2. 問題3. 設計理念4. 支持的能力5. 代碼實現 5.1. datetime.h5.2. timecount.cpp 6. 測試代碼7. 運行結果8. 源碼地址 1. 關鍵詞 C 時間處理 日期時間類 跨平臺 2. 問題 為什么C就沒有一個方便好用的表示日期時間的類&#xff1f; 同樣是高級語言&#xff0c;Ja…

2024 HGDD 榮耀開發者日·成都站

HGDD 榮耀開發者日成都站 活動時間&#xff1a;2024 年 5 月 27 日 活動地點&#xff1a;成都市雙流區 LA CADIERE 蔚藍湖濱城 期待與大家的見面&#xff01;

ISO 9001認證 要換版了!

ISO TC176/SC2 第50次會議2023年10月8日至13日在盧旺達基加利舉行。 會議確定ISO 9001標準的修訂從2024年1月開始&#xff0c;將包括WD&#xff08;Working Draft&#xff09;、CD&#xff08; Committee Draft&#xff09;、DIS&#xff08;Draft for International Standard&…

js+vue3+elementplus發送驗證碼實現(含倒計時重新發送)

<template><el-form :model"formValue" :rules"rules" ref"form"><el-form-item prop"phone"><el-input v-model.number"formValue.phone" class"form-input" placeholder"請輸入手機號…

[matlab]yalmip國內源yalmip下載地址所有版本匯總

概述 MATLAB是一個強大的數值計算工具&#xff0c;用于數學建模、算法開發和數據分析。在MATLAB中&#xff0c;有很多工具箱可以幫助用戶完成不同類型的任務。本文將介紹如何在MATLAB中安裝Yalmip和Cplex&#xff0c;這兩個工具箱可以幫助用戶解決優化問題。 如果不想看文字描…

【oracle004】oracle內置函數手冊總結(已更新)

1.熟悉、梳理、總結下oracle相關知識體系。 2.日常研發過程中使用較少&#xff0c;隨著時間的推移&#xff0c;很快就忘得一干二凈&#xff0c;所以梳理總結下&#xff0c;以備日常使用參考 3.歡迎批評指正&#xff0c;跪謝一鍵三連&#xff01; 總結源文件資源下載地址&#x…

RoctetMQ使用(2):在項目中使用

一、導入相關依賴 在項目中引入MQ客戶端依賴&#xff0c;依賴版本最好和RocketMQ版本一致。 <!-- rocket客戶端--><dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version&…

npm常用指令

基礎 命令&#xff1a;run 解釋&#xff1a;運行腳本 示例&#xff1a;npm run dev 命令&#xff1a;list || ls 解釋&#xff1a;查看依賴列表 示例&#xff1a;npm list || npm ls 命令&#xff1a;install || i 解釋&#xff1a;安裝依賴 示例&#xff1a;npm install ||…