算法入門--動態規劃(C++)

深入淺出掌握動態規劃核心思想,圖文并茂+實戰代碼

什么是動態規劃?

動態規劃(Dynamic Programming, DP) 是一種高效解決多階段決策問題的方法。它通過將復雜問題分解為重疊子問題,并存儲子問題的解(避免重復計算),最終解決原問題。

動態規劃適用場景

  • 重疊子問題:問題可分解為重復出現的子問題

  • 最優子結構:問題的最優解包含子問題的最優解

  • 無后效性:當前狀態一旦確定,后續決策不受之前決策影響

一、從斐波那契數列入門(記憶化搜索)

斐波那契數列是理解DP思想的完美起點:F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)

1.1 遞歸解法(低效)

int fib(int n) {if (n <= 1) return n;return fib(n-1) + fib(n-2);
}

問題:存在大量重復計算,時間復雜度O(2^n)

1.2 記憶化搜索(自頂向下)

#include <vector>
using namespace std;int fibMemo(int n, vector<int>& memo) {if (n <= 1) return n;if (memo[n] != -1) return memo[n]; // 已計算過memo[n] = fibMemo(n-1, memo) + fibMemo(n-2, memo);return memo[n];
}int fib(int n) {vector<int> memo(n+1, -1); // 初始化記憶數組return fibMemo(n, memo);
}

優點:時間復雜度降為O(n),空間復雜度O(n)

二、數塔問題(經典DP)

問題描述:從塔頂到塔底,每次只能向下或右下移動,求最大路徑和。

        5/ \8   3/ \ / \12  7  16/ \ / \ / \4   10  11  6

2.1 DP解法思路

  1. 狀態定義:dp[i][j]表示從第i行第j列出發到底部的最大路徑和

  2. 狀態轉移:dp[i][j] = a[i][j] + max(dp[i+1][j], dp[i+1][j+1])

  3. 邊界條件:最底層dp值等于元素本身

2.2 C++實現

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int maxPathSum(vector<vector<int>>& tower) {int n = tower.size();vector<vector<int>> dp(n, vector<int>(n, 0));// 初始化最后一行for (int j = 0; j < n; ++j) dp[n-1][j] = tower[n-1][j];// 自底向上計算for (int i = n-2; i >= 0; --i) {for (int j = 0; j <= i; ++j) {dp[i][j] = tower[i][j] + max(dp[i+1][j], dp[i+1][j+1]);}}return dp[0][0];
}int main() {vector<vector<int>> tower = {{5},{8, 3},{12, 7, 16},{4, 10, 11, 6}};cout << "最大路徑和: " << maxPathSum(tower) << endl; // 輸出: 5+8+7+11=31return 0;
}

三、最長上升子序列(LIS)

問題描述:給定數組,找到最長嚴格遞增子序列的長度 示例:[10,9,2,5,3,7,101,18] -> 最長上升子序列[2,5,7,101]長度為4

3.1 DP解法

  1. 狀態定義:dp[i]表示以nums[i]結尾的LIS長度

  2. 狀態轉移:

  3. 結果:max(dp[0...n-1])

3.2 C++實現

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int lengthOfLIS(vector<int>& nums) {if (nums.empty()) return 0;vector<int> dp(nums.size(), 1);int maxLen = 1;for (int i = 1; i < nums.size(); ++i) {for (int j = 0; j < i; ++j) {if (nums[i] > nums[j]) {dp[i] = max(dp[i], dp[j] + 1);}}maxLen = max(maxLen, dp[i]);}return maxLen;
}int main() {vector<int> nums = {10,9,2,5,3,7,101,18};cout << "最長上升子序列長度: " << lengthOfLIS(nums) << endl; // 輸出4return 0;
}

時間復雜度:O(n2) 優化:二分查找可優化至O(nlogn)

四、0-1背包問題(經典DP)

問題描述:給定n件物品(重量w[i], 價值v[i])和容量為C的背包,如何裝包使總價值最大?

4.1 DP解法思路

  1. 狀態定義:dp[i][j]表示前i件物品放入容量為j的背包的最大價值

  2. 狀態轉移:

4.2 C++實現

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int knapsack(int C, vector<int>& w, vector<int>& v) {int n = w.size();vector<vector<int>> dp(n+1, vector<int>(C+1, 0));for (int i = 1; i <= n; ++i) {for (int j = 1; j <= C; ++j) {if (j < w[i-1]) {  // 注意下標偏移dp[i][j] = dp[i-1][j];} else {dp[i][j] = max(dp[i-1][j], v[i-1] + dp[i-1][j - w[i-1]]);}}}return dp[n][C];
}int main() {vector<int> weights = {2, 3, 4, 5};  // 物品重量vector<int> values = {3, 4, 5, 6};   // 物品價值int capacity = 8;                    // 背包容量cout << "最大價值: " << knapsack(capacity, weights, values) << endl; // 輸出: 10 (選3+5+6)return 0;
}

五、動態規劃解題步驟總結

  1. 定義狀態:明確dp數組的含義

  2. 確定轉移方程:關鍵步驟,找出狀態間關系

  3. 初始化:設置邊界值

  4. 確定計算順序:自底向上或自頂向下

  5. 輸出結果:從最終狀態獲取答案

  6. 空間優化:滾動數組等技巧(可選)

六、常見DP模型

問題類型

典型問題

狀態轉移特征

線性DP

最長上升子序列

沿數組順序轉移

區間DP

矩陣鏈乘法、石子合并

從小區間向大區間轉移

背包問題

0-1背包、完全背包

物品選擇決策

樹形DP

二叉樹最大路徑和

在樹結構上遞歸轉移

狀態壓縮DP

旅行商問題(TSP)

用二進制表示狀態

掌握動態規劃需要多練習!建議從LeetCode簡單DP題開始,逐步提升難度。

推薦練習:

  • 70. 爬樓梯

  • 53. 最大子數組和

  • 322. 零錢兌換

  • 1143. 最長公共子序列

通過本文的學習,相信你已經掌握了動態規劃的基本思想和常見問題的解決方法。繼續堅持練習,很快你就能在算法解題中靈活運用DP技巧!

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

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

相關文章

[2025CVPR]GNN-ViTCap:用于病理圖像分類與描述模型

論文結構解析? 本文采用經典學術論文結構: ?引言?:闡述病理圖像分析的挑戰與現有方法局限性?相關工作?:系統梳理MIL、視覺語言預訓練和生物醫學語言模型三大領域?方法?:詳細闡述GNN-ViTCap四階段架構?實驗?:在BreakHis和PatchGastric數據集驗證性能?討論?:通…

Java SE--圖書管理系統模擬實現

一.設計思路首先這個系統可以由倆種用戶使用&#xff0c;分別為管理者用戶和普通者用戶&#xff0c;根據不同的用戶有不同的界面&#xff0c;每個界面有不同的功能。二.代碼實現創建三個包和一個類book包&#xff1a;包括Book類和Booklist類Book類&#xff1a;package book; pu…

[RPA] 批量數據抓取指定商品名稱信息

影刀RPA案例&#xff1a;批量數據抓取指定商品名稱信息流程圖&#xff1a;操作步驟&#xff1a;涉及的影刀RPA大致指令&#xff1a; 1. 打開影刀商城頁面 2. 使用【填寫輸入框(web)】指令輸入用戶名和密碼&#xff0c;并點擊"登錄"按鈕 3. 切換到"訂單管理"…

我的世界Java版1.21.4的Fabric模組開發教程(十四)方塊實體

這是適用于Minecraft Java版1.21.4的Fabric模組開發系列教程專欄第十四章——方塊實體。想要閱讀其他內容&#xff0c;請查看或訂閱上面的專欄。 方塊實體(Block Entity) 指的是一種用于存儲方塊額外數據的方法。但這種數據和為了控制方塊狀態而在自定義方塊類中創建的屬性不太…

【UE教程/進階】UE中的指針與引用

目錄直接屬性引用共享指針 TSharedPtr實現原理共享引用 TSharedRef弱引用指針 TWeakPtrObject弱指針 FWeakPtr實現原理Object軟指針 FSoftObjectPtr原理直接屬性引用 在c通過UPROPERTY()宏將屬性公開&#xff0c;藍圖中屬性類型中的Object Reference。 對一個類型及其子類型的…

早期 CNN 的經典模型—卷積神經網絡(LeNet)

目錄 LeNet 的設計背景與目標 LeNet 的網絡結構&#xff08;經典 LeNet-5&#xff09; 局部感受野詳解 一、局部感受野和全連接網絡的區別 1. 傳統全連接網絡的問題 2. 局部感受野的解決方案 二、局部感受野的優勢 1. 參數大幅減少 2. 提取局部特征 3. 平移不變性 參數…

RabbitMQ 高級特性之延遲隊列

1. 簡介 在某些場景下&#xff0c;當生產者發送消息后&#xff0c;可能不需要讓消費者立即接收到&#xff0c;而是讓消息延遲一段時間后再發送給消費者。 2. 實現方式 2.1 TTL 死信隊列 給消息設置過期時間后&#xff0c;若消息在這段時間內沒有被消費&#xff0c;就會將消…

uniapp app安卓下載文件 圖片 doc xls 數據流文件 app安卓本地路徑下載保存

//下載圖片 downloadToLocal() {plus.android.requestPermissions([android.permission.WRITE_EXTERNAL_STORAGE],(success) > {uni.saveImageToPhotosAlbum({filePath: /static/x.png,//本地地址success: () > {this.$refs.uToast.show({message: "模版下載成功&am…

Context Engineering:從Prompt Engineering到上下文工程的演進

最近在做Deepresearch以及刷到一個不錯的文章&#xff1a;context-engineering-guide &#xff0c;這篇文章揭示了提示工程以及上下文過程在智能體應用開源流程中&#xff0c;包括Deepresearch&#xff0c;MCP在內的一些概念&#xff0c;起到了非常重要的作用&#xff01; Cont…

jenkins部署vue前端項目

文章目錄前言一、安裝nginx二、jenkins構建項目總結前言 前面已經使用jenkins部署了后端springboot項目&#xff0c;現在開始學習jenkins部署前端Vue項目。 一、安裝nginx 訪問nginx官網&#xff0c;https://nginx.org/en/download.html下載tar包 上傳到服務器目錄中 然后到…

設計總監年中復盤:用Adobe XD內容識別布局,告別“手動調距”

時至年中&#xff0c;這不僅是檢視上半年項目成果的節點&#xff0c;更是優化團隊工作流、為下半年挑戰儲備動能的關鍵時期。在海外設計界工作的十余年間&#xff0c;我發現&#xff0c;一個高效的設計團隊與一個疲于奔命的團隊之間&#xff0c;最大的差別往往就在于是否建立了…

Unity 在Rider中通過Lingma插件使用MCP

環境&#xff1a; Unity 2022.3.12f1 JetBrains Rider 2025.1.4 Lingma 2.5.14 Python 3.13.4 下載包 首先在unity package manager 加入unity-mcp包 https://github.com/justinpbarnett/unity-mcp.git 然后下載uv包&#xff08;要先先下載python&#xff09;,網上很多…

pycharm+SSH 深度學習項目 遠程后臺運行命令

pycharmSSH 深度學習項目 遠程后臺運行命令碎碎念&#xff0c;都是實驗室里那說關機就關機&#xff0c;說重啟就重啟的臺式機逼得。。學吧記錄 運行&#xff1a;nohup /root/miniconda3/bin/python -u "run.py" > /root/log/nohup.log 2>&1 &實時查看日…

【Linux | 網絡】應用層(HTTP)

目錄一、認識URL二、urlencode和urldecode三、HTTP協議格式&#xff08;使用Fiddler抓包&#xff09;3.1 安裝并使用Fiddler抓包3.2 HTTP協議格式3.2.1 HTTP請求3.2.1.1 資源URL路徑3.2.1.2 請求方法&#xff08;Method&#xff09;3.2.1.3 Location頭字段&#xff08;重定向相…

編程實踐:單例模式(懶漢模式+餓漢模式)

說明:本專欄文章有兩種解鎖方案 1:付費訂閱,暢享所有文章 2:免費獲取,點擊下方鏈接,關注,自動獲取免費鏈接 https://free-img.400040.xyz/4/2025/04/29/6810a50b7ac8b.jpg 主題:C++ 單例模式 什么是單例模式

破局電機制造四大痛點:MES與AI視覺的協同智造實踐

萬界星空科技電機行業MES系統解決方案是針對電機制造過程中多工序協同難、質量追溯復雜、設備管理要求高等痛點設計的數字化管理系統。一、電機行業的核心痛點1. 多工序協同困難 電機制造涉及繞線、裝配、測試等多道工序&#xff0c;工藝銜接復雜&#xff0c;傳統人工調度效率…

HTML 初體驗

HTML&#xff08;超文本標記語言&#xff09;全稱&#xff1a;HyperText Markup Language。超文本是什么&#xff1f;答&#xff1a;超文本就是網頁中的鏈接。標記是什么&#xff1f;答&#xff1a;標記也叫標簽&#xff0c;是帶尖括號的文本。需求1&#xff1a;將“我愛中國”…

網絡層TCP機制

1.確認應答機制由于發送信息的距離可能較遠,可能出現后發的信息先到的情況,怎么辦?TCP將每個字節的數據都進行了編號,即為序列號如何分辨一個數據包是普通數據還是應答數據呢2.超時重傳由于丟包是一個隨機的事件,因此在上述tcp傳輸的過程中,丟包就存在兩種情況但是在發送方的角…

【一起來學AI大模型】微調技術:LoRA(Low-Rank Adaptation) 的實戰應用

LoRA&#xff08;Low-Rank Adaptation&#xff09; 的實戰應用&#xff0c;使用 Hugging Face 的 peft (Parameter-Efficient Fine-Tuning) 庫對大型語言模型進行高效微調。LoRA 因其顯著降低資源消耗&#xff08;顯存和計算&#xff09;同時保持接近全量微調性能的特點&#x…

RedisJSON 內存占用剖析與調優

一、基礎內存模型指針包裝 所有 JSON 值&#xff08;標量、對象、數組、字符串等&#xff09;至少占用 8 字節&#xff0c;用于存儲一個帶類型標記的指針。標量與空容器 null、true、false、小整數&#xff08;靜態緩存&#xff09;、空字符串、空數組、空對象 均不分配額外內存…