算法學習筆記(8.1)-動態規劃入門

目錄

問題特性:

最優子結構:

代碼示例:(動態規劃最優子結構)

上述最小代價爬樓梯的運行過程:

代碼示例:

無后效性:

解析:

具體過程圖示如下:

具體的代碼示例:

解析:

問題特性:

動態規劃的基本是通過子問題分解來求解原問題的。但是通俗來說,子問題分解是一種通用的算法思路,在分治、動態規劃、回溯中的側重點也不同。?

  1. 分治問題:遞歸地將原問題劃分為多個相互獨立的子問題,直至最小子問題,并在回溯中合并子問題的解,最終得到原問題的解
  2. 動態規劃:對問題進行遞歸分解,但與分治算法的主要區別是,動態規劃中的子問題是相互依賴的,在分解過程中會出現許多重疊的子問題。
  3. 回溯:在嘗試和回退中窮舉所有的可能的解,并通過剪枝避免不必要的搜索分支。原問題的解由一系列決策步驟構成,我們可以將每個決策步驟之前的子序列看作一個子問題

實際上,動態規劃常用來求解最優化問題,它不僅包含重疊子問題,還具有兩大特性:最優子結構,無后效性。

最優子結構:

給定一個樓梯,你每步可以上1階或者2階,每一個樓梯上都貼有一個非負整數,表示你在該臺階所需要付出的代價。給定一個非負整數數組cost,其中cost[i]表示在第i個臺階需要付出的代價,cost[0]為地面(起始點)。

請計算最少需要付出多少代價才能到達頂部。

若第1,2,3階的代價分別為1,10,1,則地面爬到第3階的最小代價為2.

設dp[i]為爬到第i個臺階付出的代價,由于第i階只能從i-1階或者i-2階走來,因此dp[i]只可能等于dp[i-1] + cost[i] 或者 dp[i-2] + cost[i]。為了盡可能減少代價,我們應該選擇兩者居中較小的那個:

dp[i] = min(dp[i-1],dp[i-2]) + cost[i]

這里就可以直接得出最優字結構的含義:原問題的最優解是從子問題的最優解構建而來。

但是對于爬樓梯的最優子結構,我們又該怎么理解呢,它的目標是求解方案數量,但是我們將其理解稱為最大方案數量,雖然題目的含義一樣,但是在這里出現了最優子結構的痕跡:第n階方案最大數量=第n-1階和第n-2階最大方案數量和

根據狀態轉移方程,以及初始狀態dp[1] = cost[1]和dp[2] = cost[2]。

代碼示例:(動態規劃最優子結構)

# python 代碼示例
def min_cost_climbing_stairs_dp(cost) :n = len(cost) - 1if n == 1 or n == 2 :return cost[n]dp = [0] * (n + 1)dp[1], dp[2] = cost[1], cost[2]for i in range(3, n + 1) :dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]return dp[n]
// c++ 代碼示例
int minCostClimbingStairsDP(vector<int> &cost)
{int n = cost.size() - 1 ;if (n == 1 || n == 2){return cost[n] ;}vector<int> dp(n + 1) ;dp[1] = cost[1] ;dp[2] = cost[2] ;for (int i = 3; i <= n ; i++){dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i] ;}return dp[n] ;
}

上述最小代價爬樓梯的運行過程:

將上述代碼進行空間優化,將一維壓縮至0維,空間復雜度由O(n)變為O(1)

代碼示例:

# python 代碼示例
def min_cost_climbing_stairs_dp_comp(cost) :n = len(cost) - 1if n == 1 or n == 2 :return cost[n]a, b = cost[1], cost[2]for i in range(3, n + 1) :a, b = b, min(a, b) + cost[i]return b
// c++ 代碼示例
int minCostClimbingStairsDPComp(vector<int> &cost)
{int n = cost.size() - 1 ;if (n == 1 || n == 2){return cost[n] ;}int a = cost[1], b = cost[2] ;for (int i = 3 ; i <= n ; i++){int temp = b ;b = min(a, b) + cost[i] ;a = temp ;}return b ;
}

無后效性:

能夠有效解決問題的重要特性之一,定義:給定一個確定的狀態,它的未來發展只與當前的狀態有關,而與過去經歷的所有狀態無關。

以爬樓梯進行相關理解,給定狀態i,它會發展出狀態i+1和狀態i+2,分別對應跳1步和跳2步。在做出這兩種選擇時,無須考慮狀態i之前的狀態,它們對i的未來沒有影響。

但是下面這種情況就不一樣了:如題,給定一個共有n階的樓梯,你每一步可以上1階或者2階,但是不能連續兩次跳1階,請問有多少種方案可以爬到樓頂?

如圖所示:爬3階的例子

解析:

如果上一輪跳1階上來的,下一次跳動必須跳2階。這就意味著,下一步的選擇不能由當前狀態(當前所在樓梯階數)獨立決定,還和前一個狀態(上一輪的樓梯的階數)有關。

所以原來的狀態轉移方程dp[i] = dp[i-1] + dp[i-2]也因此失效,為了滿足約束條件,我們不能直接將dp[i-1]直接放入到dp[i]中。

為此,我們需要擴展狀態定義:狀態[i,j]表示處在第i階并且上一輪跳了j階,其中j屬于{1,2}。此狀態定義有效地區分了上一輪跳了1階還是2階,我們可以根據判斷當前狀態從何而來。

  1. 當上一輪跳了1階時,上上一輪只能選擇跳2階,即dp[i,1]只能從dp[i-1,2]轉移過來
  2. 當上一輪跳了2階時,上上一輪可選擇跳1階或者跳2階,即dp[i,2]可以從dp[i-2,1]或dp[i-2,2]轉移過來。

因此,在該定義下,dp[i,j]表示狀態[i,j]對應的方案數。狀態轉移方程為:

dp[i,1] = dp[i-1,2]

dp[i,2] = dp[i-2,1] + dp[i-2,2]

具體過程圖示如下:

最終,返回dp[n,1] + dp[n,2]即可,兩者之和代表爬到第n階的方案總數:

具體的代碼示例:

# python 代碼示例
def climbing_stairs_constraint_dp(n) :if n == 1 or n == 2 :return 1dp = [ [0] * 3 for _ in range(n + 1)]dp[1][1], dp[1][2] = 1, 0dp[2][1], dp[2][2] = 0, 1for i in range(3, n + 1) :dp[i][1] = dp[i - 1][2]dp[i][2] = dp[i - 2][1] + dp[i - 2][2]return dp[n][1] + dp[n][2]
// c++ 代碼示例
int climbingStairsConstraintDP(int n)
{if (n == 1 || n == 2){return 1 ;}vector<vector<int>> dp(n + 1, vector<int>(3, 0)) ;dp[1][1] = 1 ;dp[1][2] = 0 ;dp[2][1] = 0 ;dp[2][2] = 1 ;for (int i = 3 ; i <= n ; i++){dp[i][1] = dp[i - 1][2] ;dp[i][2] = dp[i - 2][1] + dp[i - 2][2] ;}return dp[n][1] + dp[n][2] ;
}

解析:

在上面的約束條件中只需要考慮一個約束對象,因此我們可以通過擴展狀態定義,使得問題重新滿足無后效性,

給定一個共有?i?階的樓梯,你每步可以上?1?階或者?2?階。規定當爬到第?i?階時,系統自動會在第?2i?階上放上障礙物,之后所有輪都不允許跳到第?2i?階上。例如,前兩輪分別跳到了第?2、3?階上,則之后就不能跳到第?4、6?階上。請問有多少種方案可以爬到樓頂?

在這個問題中,下次跳躍依賴過去所有的狀態,因為每一次跳躍都會在更高的階梯上設置障礙,并影響未來的跳躍。對于這類問題,動態規劃往往難以解決。

實際上,許多復雜的組合優化問題(例如旅行商問題)不滿足無后效性。對于這類問題,我們通常會選擇使用其他方法,例如啟發式搜索、遺傳算法、強化學習等,從而在有限時間內得到可用的局部最優解。

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

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

相關文章

如何為IP申請SSL證書

目錄 以下是如何輕松為IP地址申請SSL證書的詳細步驟&#xff1a; 申請IP證書的基本條件&#xff1a; 申請IP SSL證書的方式&#xff1a; 確保網絡通信安全的核心要素之一&#xff0c;是有效利用SSL證書來加密數據傳輸&#xff0c;特別是對于那些直接通過IP地址訪問的資源。I…

使用 Azure DevOps Pipelines 生成 .NET Core WebJob 控制臺應用 CI/CD

Web 應用程序通常需要作為后臺任務運行的進程&#xff0c;并在特定時間間隔進行計劃或在事件中觸發。它們不需要花哨的 IO 接口&#xff0c;因為重點是過程而不是輸出。Azure WebJobs 提供了出色的支持&#xff0c;通常在云環境中通過 Web 控制臺應用程序來實現此目的。WebJob …

企業數字化轉型中的低代碼開發平臺應用:釋放創新潛能

隨著信息技術的飛速發展&#xff0c;企業數字化轉型已成為行業趨勢。在這場轉型浪潮中&#xff0c;低代碼開發平臺以其獨特的優勢&#xff0c;成為眾多企業實現快速迭代、高效創新的得力助手。本文將深入探討低代碼開發平臺在企業數字化轉型中的應用&#xff0c;以及如何幫助企…

Mac平臺虛擬機 Parallels Desktop v19.4.1,支持M1/M2/M3芯片組

Parallels Desktop for Mac是功能強大靈活度高的虛擬化方案&#xff0c;無需重啟即可在同一臺電腦上隨時訪問Windows和Mac兩個系統上的眾多應用程序。從僅限于PC的游戲到生產力軟件&#xff0c;Parallels Desktop都能幫您實現便捷使用。Parallels Desktop 是一款專業的Mac虛擬機…

Docker搭建kafka+zookeeper以及Springboot集成kafka快速入門

參考文章 【Docker安裝部署KafkaZookeeper詳細教程】_linux arm docker安裝kafka-CSDN博客 Docker搭建kafkazookeeper 打開我們的docker的鏡像源配置 vim /etc/docker/daemon.json 配置 { "registry-mirrors": ["https://widlhm9p.mirror.aliyuncs.com"…

vue父子組件通信實現模糊搜索功能

我遇到的問題&#xff1a; 我的搜索框在父頁面&#xff0c;靜態數據都在子頁面。怎么實現模糊查詢數據&#xff1f; 昨天的嘗試&#xff1a;先把搜索的內容數據存到session里&#xff0c;然后從session里拿&#xff0c; 結果&#xff1a;存是存進去了&#xff0c;卻拿不到。應…

Django學習收尾

啟動項目命令 python manage.py runserver 文件上傳功能實現 title "Form上傳"if request.method "GET":form UpForm()return render(request, upload_form.html, {"form": form, "title": title})form UpForm(datarequest.POS…

Java對象創建究竟是在棧上還是堆上??

在 Java 中&#xff0c;對象的創建通常情況下是在堆上。 基本數據類型&#xff08;如 byte、short、int、long、float、double、char&#xff09;在方法內聲明時&#xff0c;其值會存儲在棧上。除了基本數據類型之外的所有對象&#xff0c;都是由 Java 虛擬機&#xff08;JVM&…

python入門基礎知識·二

""" # Python介紹 # Python注釋 # 單行注釋&#xff1a; # # 多行注釋&#xff1a; r """""" # Python輸出和輸入 # print: 輸出 # input: 輸入 ①會讓程序暫停&#xff0c;②得到的是字符串內容 int(&…

Linux Mac 安裝Higress 平替 Spring Cloud Gateway

Linux Mac 安裝Higress 平替 Spring Cloud Gateway Higress是什么?傳統網關分類Higress定位下載安裝包執行安裝命令執行腳本 安裝成功打開管理界面使用方法configure.shreset.shstartup.shshutdown.shstatus.shlogs.sh Higress官網 Higress是什么? Higress是基于阿里內部的…

Vue指令詳解與實操運用 - 編程魔法

在Vue.js的世界里&#xff0c;指令就像是一位魔法師&#xff0c;它們能夠賦予HTML元素以生命&#xff0c;讓網頁與用戶互動起來。今天&#xff0c;我們就來揭開這些指令的神秘面紗&#xff0c;看看它們是如何在我們的日常開發中發揮作用的。 1. v-text 和 v-html - 文字與內容的…

思考:Java內存模型和硬件內存模型

前言 前一陣在看volatile的原理&#xff0c;看到內存屏障和緩存一致性&#xff0c;發現再往底層挖就挖到了硬件和Java內存模型。這一塊是自己似懂非懂的知識區&#xff0c;我一般稱之為知識混沌區。因此整理這一篇文章。 什么是內存模型&#xff08;Memory Model&#xff09;…

CentOS6用文件配置IP模板

CentOS6用文件配置IP模板 到 CentOS6.9 , 默認還不能用 systemctl , 能用 service chkconfig sshd on 對應 systemctl enable sshd 啟用,開機啟動該服務 ### chkconfig sshd on 對應 systemctl enable sshd 啟用,開機啟動該服務 sudo chkconfig sshd onservice sshd start …

未羽研發測試管理平臺

突然有一些覺悟&#xff0c;程序猿不能只會吭哧吭哧的低頭做事&#xff0c;應該學會怎么去展示自己&#xff0c;怎么去宣傳自己&#xff0c;怎么把自己想做的事表述清楚。 于是&#xff0c;這兩天一直在整理自己的作品&#xff0c;也為接下來的找工作多做點準備。接下來…

LT7911UX 國產原裝 一拖三 edp 轉LVDS 可旋轉 可縮放

2.一般說明 該LT7911UX是一種高性能Type-C/DP1.4a到MIPI或LVDS芯片的VR/顯示應用。HDCP RX作為HDCP轉發器的上游&#xff0c;可以與其他芯片的HDCP TX配合實現轉發器功能。 對于DP1.4a輸入&#xff0c;LT7911UX可配置為1/2/4通道。自適應均衡使其適用于長電纜應用&#xff0c;最…

Junior.Crypt.2024 CTF Web方向 題解WirteUp 全

Buy a cat 題目描述&#xff1a;Buy a cat 開題 第一思路是抓包改包 Very Secure App 題目描述&#xff1a;All secrets become clear 開題 亂輸一個密碼就登陸成功了&#xff08;不是弱口令&#xff09; 但是回顯Your role is: user 但是有jwt&#xff01;&#xff01;&a…

深入理解基本數據結構:鏈表詳解

引言 在計算機科學中&#xff0c;數據結構是存儲、組織和管理數據的方式。鏈表是一種重要的線性數據結構&#xff0c;廣泛應用于各種編程場景。在這篇博客中&#xff0c;我們將詳細探討鏈表的定義、特點、操作及其在不同編程語言中的實現。 什么是鏈表&#xff1f; 鏈表是一種…

Mobile ALOHA前傳之VINN, Diffusion Policy和ACT對比

VINNDiffusion PolicyACT核心思想1.從離線數據中自監督學習獲得一個視覺編碼器&#xff1b;2.基于視覺編碼器&#xff0c;從采集的示例操作數據中檢索與當前觀測圖像最相似的N張圖像以及對應的動作&#xff1b;3.基于圖像編碼器的距離對各個動作進行加權平均&#xff0c;獲得最…

Open3D loss函數優化的ICP配準算法(精配準)

目錄 一、概述 1.1ICP的基本步驟 1.2損失函數的設計 二、代碼實現 2.1關鍵函數 2.2完整代碼 三、實現效果 3.1原始點云 3.2配準后點云 3.3計算數據 一、概述 ICP(Iterative Closest Point)配準算法是一種用于對齊兩個點云的經典算法。其目標是通過迭代優化…

Istio實戰教程:Service Mesh部署與流量管理

引言 Istio是一個開源的服務網格&#xff0c;它提供了一種統一的方法來連接、保護、控制和觀察服務。本教程將指導你從零開始部署Istio&#xff0c;并展示如何使用Istio進行基本的流量管理。 環境準備 Kubernetes集群&#xff1a;Istio運行在Kubernetes之上&#xff0c;確保…