算法導論實戰(三)(算法導論習題第二十四章)

🌈?個人主頁:十二月的貓-CSDN博客
🔥?系列專欄:?🏀算法啟示錄

💪🏻?十二月的寒冬阻擋不了春天的腳步,十二點的黑夜遮蔽不住黎明的曙光?

目錄

前言

第二十四章?

24.1-3

24.1-4

24.2-4

24.3-2?

24.3-3

24.3-6

24.3-8

24.3-10?

總結


前言

算法導論的知識點學習將持續性更新在算法啟示錄_十二月的貓的博客-CSDN博客,歡迎大家訂閱呀(反正是免費的哦~~)

實戰篇也將在專欄上持續更新,主要目的是強化對理論的學習(題目來源:山東大學孔凡玉老師推薦)

第二十四章?

24.1-3

問題描述

假設給定G=(V,E)是一帶權重且沒有權重為負值的環路的有向圖,對于所有的結點𝑣∈𝑉,從源結點s到結點v之間的最短路徑中,包含邊的條數的最大值為m。請對算法BELLMAN-FORD進行簡單修改,可以讓其在m+1遍松弛操作之后終止,即使m不是事先知道的一個數值。

問題分析:

如果一個圖所有節點到源點s的距離包含的邊的條數的最大值為m,那么意味算法在進行m輪松弛后,整個圖的所有節點都已經得到最短路徑。此時不再需要繼續執行m+1輪松弛

問題求解
在BELLMAN-FORD算法的2-4行的執行記錄下松弛前各點的最短路徑長度,如果某一次松弛循環結束時所有v.d的值跟本次循環開始時v.d的值相比不發生改變時,此次循環即為第m+1次。?

INITALIZE-SINGLE-SOURCE(G,s)
for i=1 to |G.V|-1for each v in G.Vsave v.d to Tfor each edge(u,v) in G.ERELAX(u,v,w)for each v in G.Vif v.d != T[v].dcontinue //沒有點的值被更新,說明所有點都取到最短路徑,則停止for each edge(u,v) in G.Eif v.d>u.d+w(u,v)return FALSEreturn TRUE

24.1-4

問題描述:
修改Bellman-Ford算法,使其對于所有結點v來說,如果從源結點s都結點v的一條路徑上存在權重為負值的環路,則將v.d的值設置為?∞。

問題分析:

貝爾曼福德算法不能夠處理存在權重為負值的環路,因為一旦存在則會一直在環路上循環,因為這樣的最短路徑值會不停縮短。該情況顯然是我們不希望發生的,所以我們增加這一個功能來應對存在負值環路的特殊情況。

問題求解:

如果存在負權環路,那么w(u,v)就是無窮小,并且w(s,v)(就是v.d)也是無窮小,于是這個if語句返回值是FLASE。所以只要在if內增加對v.d的修正即可

INITALIZE-SINGLE-SOURCE(G,s)
for i=1 to |G.V|-1for each v in G.Vsave v.d to Tfor each edge(u,v) in G.ERELAX(u,v,w)for each v in G.Vif v.d != T[v].dcontinue //沒有點的值被更新,說明所有點都取到最短路徑,則停止for each edge(u,v) in G.Eif v.d>u.d+w(u,v)v.d=-∞return FALSEreturn TRUE

24.2-4

問題描述:

給出一個有效的算法來計算一個有向無環圖中的點的路徑總數。分析你自己的算法。

問題分析:

目前我們手頭關于圖的知識點只有圖的基本算法+最短路徑算法+最小生成樹,利用這些知識點來思考如何找路徑總數。考慮到本題不用考慮有權圖,所以我們把眼光轉向BFS和DFS兩個算法。進一步思考,我們能知道BFS常常用在求解最短路徑算法中(BFS特點在于得到的是一棵樹,同時每個點都是最短路徑的),在這里我們需要求解的是到一個點的所有路徑。

假如我們有如下一個圖,現在要我們來求解頂點6的路徑數

樸素想法:我們最樸素的想法就是從頂點1、2、3、5、4、....、這樣的順序去求解路徑數。于是我們可以得到p(1)=1; p(2)+=p(1); p(3)+=p(1); p(5)+=p(2); p(4)+=p(2); 等等。

總的來說,就是從上層到下層計算,下層的路徑數:下層路徑數+=上層路徑數

那什么是下層?什么又是上層呢?

下層:在上層結點撤去后不存在入度結點的點;上層:存在出度給其他頂點

如果可以從上層到下層計算呢?我們就需要對圖進行拓撲排序


拓撲排序:是一種對有向圖進行排序的算法,其主要目的是確定圖中節點的線性順序,使得在排序后,所有的邊都從左到右指向更大的節點。換句話說,拓撲排序可以將圖中的節點按照其依賴關系進行排序,使得所有的依賴關系都被滿足。

?實現拓撲排序的方法有兩個:一、計算結點入度+隊列方法(通用方法)二、深度搜索(用于無環路的有向圖

本題是有向無環圖可以用方法二


問題求解:

一、利用DFS搜索樹,將圖進行拓撲排序,得到拓撲排序后的圖

二、在新的圖中,按照拓撲排序的順序,對每個點u,找其所指向的點v,執行v.paths+=u.paths

PATHS(G)topologically sort the vertices of Gfor each vertex u, taken in topologically sorted orderfor each v ∈ G.Adj[u]v.paths = u.paths + v.pathsreturn the sum of all paths attributes

24.3-2?

問題描述:

請舉出一個包含負權重的有向圖,使得 Dijkstra 算法在其上運行時將產生不正確的結果。為什么在有負權重的情況下,定理 24.6 的證明不能成立呢?

問題分析:

看到對本題的其中一個解答:?

大致意思是說:如果存在負權重回路,那么這個RELAX操作是沒有意義的,因為RELEX是有限次的,但是通過負權重回路,我們到任何通過這個回路的點的距離都是?∞。于是在RELAX后,u.d并不是(s,u)的最小值,因此不成立

顯然上面的證明是沒有問題的,但是本題問的是為什么不能有負權重邊,而不是負權重回路。所以僅僅有上面的證明是不充分的

問題求解:

Dijkstra算法是貪心貪心算法,也就是說每次都選擇貪心策略下的局部最優解,這個解在后續中也不會再修正。那么對于如下的帶有負權重的有向圖:

假如源點是A,那么首先選擇C此時C值為1;后選擇B此時B的值為2,然后又會選擇C此時C的值應該要修正為0.但是C的值不會被修正,因此Dijkstra每個點只訪問一次(貪心策略)。所以最終C.d=1,但是實際上C到A的最小值為0。因此定理 24.6是不成立的,算法結束后,存在點的d的值不是最短路徑值

24.3-3

問題描述:

假定將 Dijkstra 算法的第 行改為:

4 :white(lQl)>1

這種改變將讓呻證循環的執行次數從 IVI 次降低到 IVI -1次。這樣修改后的算法正確嗎?

問題分析:

迪杰斯特拉算法最后得到的結果有兩個:一、訪問序列s,用來記錄對點的訪問次序;二、每個點的v.d記錄每個點到源點的距離。

所以正確性的證明也將從這兩個角度展開:

問題求解:

正確的!

一、假如我們已經得到前面V-1個點的訪問序列,那么最后一個點不需要放入,我們也可以只知道最終的訪問序列

二、迪杰斯特拉對每個結點只訪問一次,且每次都能確定一個點的最短路徑,此時程序運行了V-1個循環,訪問并確定了V-1個點的最短路徑。所以最后一個點進行松弛操作時,它并不能縮短其他點到原點的距離,所以最后一個點的RELAX操作也是無意義的。因此算法是正確的

24.3-6

問題描述:

問題分析:?

本題和最短路徑問題存在幾點不一樣:

一、它需要找的是最可靠,也就是值最大的路徑,可以認為是最長路徑

二、最短路徑算法相連路徑段之間的關系是求和,但是通信鏈路相連路徑段求可靠性時之間的關系是求積

問題求解:

一、最長路徑。那就把貪婪準則改為選擇d最大的點

二、總路徑和子路徑的關系變為乘。那就修改RELAX準則,從+變為*

三、初始化。源點可靠性為1;其他未搜索到的點初始化為0

INITIALIZE(G,s)for each vertex v ∈ G.Vv.d=0v.π=NULLs.d=1
DIJKSTRA(G,w,s) //s用來記錄訪問的順序,是需要返回的值;w邊的權重集合S=空集合Q=G.Vwhile(Q <> 空集合)u=EXTRACT-MAX(Q)S=S U {u}for each vertex v∈G.adj[u]RELEX(u,v,w) 
RELAX(u,v,w)if v.d<u.d*w(u,v)v.d=u.d*w(u,v)v.π=u

24.3-8

問題描述:

問題分析:

我第一次看這道題的時候,說實話,連題目都沒看懂【emmmmm】。具體原因就在權重函數w:E->{0,1,...,W}這里沒看明白。

這個權重函數就表示:邊E的權重只能取{1,2,....,W}中的數

再來看看這個WV時間復雜度是哪里來的?要解決這個問題

先讓友友們先思考另一個問題:WV含義是什么?

WV含義:圖中任意點到源點的距離上限(圖中任意點到源點的距離不超過WV)


再來思考一個這個E的時間復雜度含義又是什么?

E是指邊,也就是說我需要對邊進行E次操作,這不禁讓我們想到了松弛操作。

E的復雜度就代表我們要對所有邊進行一輪的松弛,每次松弛邊本質是更新點的V.d,所以本質就是對點進行了E次的操作

問題求解:

從優化“貪心尋找dist最小點”的操作入手。由于邊權≤W≤𝑊,那么一個點的dist值不會超過VW。基于這個條件,我們可以抽象出一個長度為VW的隊列數組。每個數組的隊列存儲著“dist值為該數組序號”的點。然后抽象出一個指針,這個指針指向的隊列,是我們貪心取點的隊列。由于一個點被取出后,被他更新的點只會被push進該隊列或者該隊列之后的隊列,所以指針只會從左到右掃描一遍數組。

最多掃描一遍數組,復雜度為O(VW)。此外,最多會有E次入隊、出隊操作,復雜度為O(E)。總時間復雜度為O(VW+E)。

#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N = ..., M = ..., W = ...;
queue<int> qs[N*W];
int head[N], ver[M], edge[M], Next[M], tot = 0;//采用數組模擬鄰接鏈表的方式
void add(int x,int y,int z){ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
}
int d[N], v[N];
int n, m, w;
void dijkstra(int s){memset(d,0x3f,sizeof(d));//初始化為正無窮memset(v,0,sizeof(v));d[s] = 0; qs[0].push(s);for(int k = 0; k<=n*w; k++){while(!qs[k].empty()){int x = qs[k].front(); qs[k].pop();if(v[x]) continue;v[x] = 1;for(int i = head[x]; i; i = Next[i]){int y = ver[i], z = edge[i];if(d[y] > d[x] + z){d[y] = d[x] + z;qs[d[y]].push(y);}}}}
}

24.3-10?

問題描述:

假設給定帶權重的有向圖 G=(V, E), 從源結點s發出的邊的權重可以為負值,而其他所有邊的權重全部是非負值,同時,圖中不包含權重為負值的環路。證明: Dijkstra 算法可以正確計算出從源結點到所有其他結點之間的最短路徑。?

問題分析:

證明Dijkstra 算法是可行的==證明一個貪心策略是有效的。考慮到Dijkstra 算法本身的貪心策略已經證明結束,所以我們只需要針對其中變化的部分進行特別論證即可

特別部分:從源結點s發出的邊的權重可以為負值

利用?Dijkstra 算法取出S,并更新與S相鄰的點,將得到多個值不為0的點

于是,該問題可以等效為:多源點且初始值不為0的最短路徑問題,并且每個源點都可以適用Dijkstra 算法

因此,整個問題同樣可以利用?Dijkstra 算法來求解

問題求解:

首先,Dijkstra的算法思路是:對于任意一個從隊列取出來的點x,如果它沒有被標記過,那么d[x]一定是源結點s到x的最短路徑,然后我們不斷地進行貪心擴展,最終可以得到源結點s到每個結點的最短路徑。它的本質是一個貪心+BFS算法。
現在,題目中給出的限制是:“只有從源結點s出發的邊權重可以為負,且圖中無負環”。
源結點s一定是在一開始被取出,更新完之后被丟棄。因為只有源結點s出發的邊權重可以為負,所以我們在后面更新由“s以外的其他點”更新“s以外的其他點”時,仍舊是在一個無負邊權的圖中的更新,所以Dijkstra仍正確。而對于這些點,當他們嘗試更新s的時候,因為圖中無負環,所以無法更新s。此外,由于無負環,s也不會出現有一個權值為負的子環無限更新自身的情況。綜上,Dijkstra基于貪心的性質沒有發生改變,每次從隊列中取出的一個點更新完其他點被丟棄后,這個點在后面一定不會被更新。所以Dijkstra仍舊可以正確運行。

總結

本文到這里就結束啦~~

本篇文章的撰寫花了本喵四個多小時

如果仍有不夠,希望大家多多包涵~~

如果覺得對你有幫助,辛苦友友點個贊哦~

知識來源:《算法導論》課后習題、山東大學孔凡玉老師ppt。不要用于商業用途轉發~

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

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

相關文章

筆記:DST與HPPC測試方法

一、DST測試方法&#xff1a; DST全稱為Dynamic Stress Test,是一種動態壓力測試方法&#xff0c;主要用于評估電池在實際使用條件下的綜合性能&#xff0c;模擬了車輛在行駛過程中可能會遇到的各種動態負載變化&#xff0c;如加速、減速、怠速等工況。 它的目的是評估電池在…

setattr前端接收方法深度解析

setattr前端接收方法深度解析 在前端開發中&#xff0c;setattr可能是一個較為陌生的概念&#xff0c;但它卻在某些場景下扮演著關鍵角色。setattr是一個Python內置函數&#xff0c;用于設置對象屬性的值。然而&#xff0c;在前端與后端交互的過程中&#xff0c;我們有時需要處…

【Week-R2】使用LSTM實現火災預測(tf版本)

【Week-R2】使用LSTM實現火災預測&#xff08;tf版本&#xff09; 一、 前期準備1.1 設置GPU1.2 導入數據1.3 數據可視化 二、數據預處理(構建數據集)2.1 設置x、y2.2 歸一化2.3 劃分數據集 三、模型創建、編譯、訓練、得到訓練結果3.1 構建模型3.2 編譯模型3.3 訓練模型3.4 模…

超詳細的java Comparable,Comparator接口解析

前言 Hello大家好呀&#xff0c;在java中我們常常涉及到對象的比較&#xff0c;不同于基本數據類型&#xff0c;對于我們的自定義對象&#xff0c;需要我們自己去建立比較標準&#xff0c;例如我們自定義一個People類&#xff0c;這個類有name和age兩個屬性&#xff0c;那么問…

[數據集][圖像分類]蘑菇分類數據集3122張215類別

數據集類型&#xff1a;圖像分類用&#xff0c;不可用于目標檢測無標注文件 數據集格式&#xff1a;僅僅包含jpg圖片&#xff0c;每個類別文件夾下面存放著對應圖片 圖片數量(jpg文件個數)&#xff1a;3122 分類類別數&#xff1a;215 類別名稱:[“almond_mushroom”,“amanita…

實驗筆記之——DPVO(Deep Patch Visual Odometry)

本博文記錄本文測試DPVO的過程&#xff0c;本博文僅供本人學習記錄用~ 《Deep Patch Visual Odometry》 代碼鏈接&#xff1a;GitHub - princeton-vl/DPVO: Deep Patch Visual Odometry 目錄 配置過程 測試記錄 參考資料 配置過程 首先下載代碼以及創建conda環境 git clo…

Data Management Controls

Data Browsing and Analysis Data Grid 以標準表格或其他視圖格式&#xff08;例如&#xff0c;帶狀網格、卡片、瓷磚&#xff09;顯示數據。Vertical Grid 以表格形式顯示數據&#xff0c;數據字段顯示為行&#xff0c;記錄顯示為列。Pivot Grid 模擬微軟Excel的樞軸表功…

有待挖掘的金礦:大模型的幻覺之境

人工智能正在迅速變得無處不在&#xff0c;在科學和學術研究中&#xff0c;自回歸的大型語言模型&#xff08;LLM&#xff09;走在了前列。自從LLM的概念被整合到自然語言處理&#xff08;NLP&#xff09;的討論中以來&#xff0c;LLM中的幻覺現象一直被廣泛視為一個顯著的社會…

Oracle EBS AP發票創建會計科目提示:APP-SQLAP-10710:無法聯機創建會計分錄

系統版本 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 問題癥狀: 提交“創建會計科目”請求提示錯誤信息如下: APP-SQLAP-10710:無法聯機創建會計分錄。 請提交應付款管理系統會計流程,而不要為此事務處理創建會計分錄解決方法 數據修復SQL腳本: UPDATE ap_invoi…

LabVIEW閥性能試驗臺測控系統

本項目開發的閥性能試驗臺測控系統是為滿足國家和企業相關標準而設計的&#xff0c;主要用于汽車氣壓制動系統控制裝置和調節裝置等產品的綜合性能測試。系統采用工控機控制&#xff0c;配置電器控制柜&#xff0c;實現運動控制、開關量控制及傳感器信號采集&#xff0c;具備數…

vue封裝一個查詢URL參數方法

vue封裝一個查詢URL參數方法 在 Vue 中&#xff0c;你可以封裝一個查詢 URL 參數的方法來獲取 URL 中的查詢參數。以下是一個示例代碼&#xff1a; export const getQueryParam (param) > {const urlParams new URLSearchParams(window.location.search);return urlPara…

算法-分治策略

概念 分治算法&#xff08;Divide and Conquer&#xff09;是一種解決問題的策略&#xff0c;它將一個問題分解成若干個規模較小的相同問題&#xff0c;然后遞歸地解決這些子問題&#xff0c;最后合并子問題的解得到原問題的解。分治算法的基本思想是將復雜問題分解成若干個較…

東方博宜1565 - 成績(score)

問題描述 牛牛最近學習了 C 入門課程&#xff0c;這門課程的總成績計算方法是&#xff1a; 總成績作業成績 20% 小測成績 30% 期末考試成績 50%。 牛牛想知道&#xff0c;這門課程自己最終能得到多少分。 輸入 三個非負整數 A、B、C &#xff0c;分別表示牛牛的作業成績、…

計算機網絡 期末復習(謝希仁版本)第3章

對于點對點的鏈路&#xff0c;目前使用得最廣泛的數據鏈路層協議是點對點協議 PPP (Point-to-Point Protocol)。局域網的傳輸媒體&#xff0c;包括有線傳輸媒體和無線傳輸媒體兩個大類&#xff0c;那么有線傳輸媒體有同軸電纜、雙絞線和光纖&#xff1b;無線傳輸媒體有微波、紅…

計算引擎:Flink核心概念

Apache Flink 是一個流處理框架,擅長處理實時數據流和批處理任務。Flink 提供了強大的功能來處理和分析大量數據。以下是 Flink 的核心概念: 1. DataStream 和 DataSet API DataStream API: 用于處理無界數據流,即不斷生成和流動的數據。例如,傳感器數據、日志等。DataSet…

基于Texture2D 實現Unity 截屏功能

實現 截屏 Texture2D texture new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false); texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0); texture.Apply(); 存儲 byte[] array ImageConversion.EncodeToPNG(texture); if (!…

分享萬能點擊器免費版,吾愛大佬出品,這個太贊了!

小伙伴們&#xff01;阿星又來給大家推薦神奇的小軟件啦&#xff01;這次的主角可是個神器——鼠標連點器&#xff01;你聽過沒&#xff1f;這玩意兒簡直是個“自動小助手”&#xff0c;讓你的鼠標在屏幕上飛舞&#xff0c;點得飛快&#xff0c;解放你的雙手&#xff0c;讓你網…

【ARM 常見匯編指令學習 6.2 -- ARMv8 匯編指令 SDIV 詳細介紹】

文章目錄 SDIV指令格式使用示例注意事項總結 SDIV ARMv8 架構中的 SDIV 指令用于執行帶符號整數除法操作。這意味著它可以處理負數除法&#xff0c;與 UDIV&#xff08;執行無符號整數除法&#xff09;形成對比。SDIV 將兩個寄存器中的帶符號整數相除&#xff0c;將除法結果存…

react學習-組件傳值

1.props傳值 主要步驟&#xff1a; 在父組件中引用子組件時&#xff0c;在子組件上面寫入name1{name2}格式進行傳值&#xff0c;name1為子組件中對應的用于接收數據的字段名稱&#xff0c;name2為父組件中需要傳遞到子組件中的值&#xff08;state中聲明的數據&#xff09;&…

一篇文章帶你搞懂C++引用(建議收藏)

引用 6.1 引用概念 引用不是新定義一個變量&#xff0c;而是給已存在變量取了一個別名&#xff0c;編譯器不會為引用變量開辟內存空間&#xff0c;它和它引用的變量共用同一塊內存空間。 比如&#xff1a;李逵&#xff0c;在家稱為"鐵牛"&#xff0c;江湖上人稱&quo…