區間動態規劃

線性 DP 的一種,簡稱為「區間 DP」。以「區間長度」劃分階段,以兩個坐標(區間的左、右端點)作為狀態的維度。一個狀態通常由被它包含且比它更小的區間狀態轉移而來。

一、概念

間 DP 的主要思想就是:先在小區間內得到最優解,再利用小區間的最優解合并,從而得到大區間的最優解,最終得到整個區間的最優解。

根據小區間向大區間轉移情況的不同,常見的區間 DP 問題可以分為兩種:

  1. 單個區間從中間向兩側更大區間轉移的區間 DP 問題。比如從區間 [i+1,j?1]轉移到更大區間 [i,j]。
  2. 多個(大于等于 2 個)小區間轉移到大區間的區間 DP 問題。比如從區間 [i,k]和區間 [k,j]轉移到區間 [i,j]。

二、區間 DP 問題的基本思路

1. 第 1 種區間 DP 問題基本思路

從中間向兩側轉移的區間 DP 問題的狀態轉移方程一般為:dp[i][j]=max{dp[i+1][j?1],dp[i+1][j],dp[i][j?1]}+cost[i][j], i <= j,。

  1. 其中 dp[i][j]表示為:區間 [i,j](即下標位置 i到下標位置 j 上所有元素)上的最大價值。
  2. cost 表示為:從小區間轉移到區間 [i,j]的代價。
  3. 這里的 max/minn 取決于題目是求最大值還是求最小值。

從中間向兩側轉移的區間 DP 問題的基本解題思路如下:

  1. 枚舉區間的起點;
  2. 枚舉區間的終點;
  3. 根據狀態轉移方程計算從小區間轉移到更大區間后的最優值
// 假設 dp 是一個二維數組,表示區間DP的狀態
// cost 表示區間內每個子問題的權值或代價// 逆序枚舉區間起點
for (let i = size - 1; i >= 0; i--) {// 枚舉區間終點for (let j = i + 1; j < size; j++) {// 狀態轉移方程,計算轉移到更大區間后的最優值dp[i][j] = Math.max(dp[i + 1][j - 1], dp[i + 1][j], dp[i][j - 1]) + cost[i][j];}
}

2. 第 2 種區間 DP 問題基本思路

// 假設 dp 是一個二維數組,表示區間DP的狀態
// cost 表示區間內每個子問題的權值或代價// 枚舉區間長度
for (let l = 1; l < n; l++) {// 枚舉區間起點for (let i = 0; i < n; i++) {// 根據起點和長度得到終點const j = i + l - 1;// 防止越界if (j >= n) {break;}// 初始化 dp[i][j]dp[i][j] = -Infinity;// 枚舉區間分割點for (let k = i; k <= j; k++) {// 狀態轉移方程,計算合并區間后的最優值dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[k + 1][j] + cost[i][j]);}}
}

三、練習

給定一個字符串 s找出其中最長的回文子序列,并返回該序列的長度。

代碼

class Solution {longestPalindromeSubseq(s) {const size = s.length;// 創建二維數組 dp,dp[i][j] 表示字符串 s 在區間 [i, j] 內的最長回文子序列的長度const dp = new Array(size).fill(0).map(() => new Array(size).fill(0));// 初始化區間長度為 1 的情況for (let i = 0; i < size; i++) {dp[i][i] = 1;}// 逆序枚舉區間起點for (let i = size - 1; i >= 0; i--) {// 枚舉區間終點for (let j = i + 1; j < size; j++) {// 如果區間兩端字符相等,則當前區間的最長回文子序列長度為左下方的長度加上 2if (s[i] === s[j]) {dp[i][j] = dp[i + 1][j - 1] + 2;} else {// 否則,取左側和下側的最大值dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);}}}// 返回整個字符串的最長回文子序列長度return dp[0][size - 1];}
}// 示例用法
const solution = new Solution();
// 輸出整個字符串的最長回文子序列長度
console.log(solution.longestPalindromeSubseq("bbbab"));

四、 案例——問題:矩陣鏈乘法問題(Matrix Chain Multiplication)

描述:
給定一系列矩陣 A1, A2, ..., An,它們的維度為 p0 × p1, p1 × p2, ..., pn-1 × pn
你的任務是決定這些矩陣的乘法順序,使得乘法總操作次數最小。

注意:矩陣乘法滿足結合律但不滿足交換律。


🧠 思路:區間動態規劃

  • 狀態定義:

    • dp[i][j] 表示計算矩陣 Ai ~ Aj 的最小乘法次數(i < j)

  • 狀態轉移:

    • 枚舉中間斷點 kdp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + p[i] * p[k] * p[j])

  • 初始化:

    • dp[i][i+1] = 0,因為兩個相鄰矩陣之間不能再分割

  • 目標:

    • dp[0][n],表示從第一個矩陣乘到最后一個矩陣的最小代價


? JavaScript 實現

function matrixChainOrder(p) {const n = p.length - 1; // 有 n 個矩陣const dp = Array.from({ length: n + 1 }, () => Array(n + 1).fill(Infinity));// 初始化對角線相鄰的 dp[i][i+1] = 0for (let i = 0; i < n; i++) {dp[i][i + 1] = 0;}// 區間長度 l 從 2 到 nfor (let len = 2; len <= n; len++) {for (let i = 0; i + len <= n; i++) {const j = i + len;for (let k = i + 1; k < j; k++) {const cost = dp[i][k] + dp[k][j] + p[i] * p[k] * p[j];if (cost < dp[i][j]) {dp[i][j] = cost;}}}}return dp[0][n];
}// 示例:矩陣 A(10x30), B(30x5), C(5x60)
// 對應的維度數組 p = [10, 30, 5, 60]
const dimensions = [10, 30, 5, 60];
console.log(matrixChainOrder(dimensions)); // 輸出最小乘法次數

🧩 示例說明:

輸入:[10, 30, 5, 60]
代表三個矩陣:

  • A1: 10x30

  • A2: 30x5

  • A3: 5x60

可以有兩種乘法順序:

  1. ((A1 * A2) * A3):代價 = 10*30*5 + 10*5*60 = 1500 + 3000 = 4500

  2. (A1 * (A2 * A3)):代價 = 30*5*60 + 10*30*60 = 9000 + 18000 = 27000

取較小值 => 最小代價為 4500

請觀看配套視頻《數據結構與算法(前端版)》

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

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

相關文章

4. 數據類型

4.1 數據類型分類 分類 數據類型 說明 數值類型 BIT(M) 位類型。M指定位數&#xff0c;默認值1&#xff0c;范圍1 - 64 TINYINT [UNSIGNED] 帶符號的范圍 -128 ~ 127&#xff0c;無符號范圍0 ~ 255&#xff0c;默認有符號 BOOL 使用0和1表示真和假 SMALLINT [UNSIGNED] 帶符號是…

設計模式-2 結構型模式

一、代理模式 1、舉例 海外代購 2、代理基本結構圖 3、靜態代理 1、真實類實現一個接口&#xff0c;代理類也實現這個接口。 2、代理類通過真實對象調用真實類的方法。 4、靜態代理和動態代理的區別 1、靜態代理在編譯時就已經實現了&#xff0c;編譯完成后代理類是一個實際…

vue+element-ui一個頁面有多個子組件組成。子組件里面有各種表單,實現點擊enter實現跳轉到下一個表單元素的功能。

一個父組件里面是有各個子組件的form表單組成的。 我想實現點擊enter。焦點直接跳轉到下一個表單元素。 父組件就是由各個子組件構成 子組件就像下圖一樣的都有個el-form的表單。 enterToTab.js let enterToTab {}; (function() {// 返回隨機數enterToTab.addEnterListener …

Open SSL 3.0相關知識以及源碼流程分析

Open SSL 3.0相關知識以及源碼流程分析 編譯 windows環境編譯1、工具安裝 安裝安裝perl腳本解釋器、安裝nasm匯編器(添加到環境變量)、Visual Studio編譯工具 安裝dmake ppm install dmake # 需要過墻2、開始編譯 # 1、找到Visual Studio命令行編譯工具目錄 或者菜單欄直接…

【Redis】筆記|第5節|Redisson實現高并發分布式鎖核心源碼

一、加鎖流程 1. 核心方法調用鏈 RLock lock redisson.getLock("resource"); lock.lock(); // 阻塞式加鎖? lockInterruptibly()? tryAcquire(-1, leaseTime, unit) // leaseTime-1表示啟用看門狗? tryAcquireAsync()? tryLockInnerAsync() // 執行Lua腳本 2…

基于React + TypeScript構建高度可定制的QR碼生成器

前言 在現代Web應用中&#xff0c;QR碼已成為連接線上線下的重要橋梁。本文將詳細介紹如何使用React TypeScript Vite構建一個功能強大、高度可定制的QR碼生成器&#xff0c;支持背景圖片、文本疊加、HTML模塊、圓角導出等高級功能。 前往試試 項目概述 技術棧 前端框架:…

【MATLAB代碼】制導——三點法,二維平面下的例程|運動目標制導,附完整源代碼

三點法制導是一種導彈制導策略,主要用于確保導彈能夠準確追蹤并擊中移動目標。該方法通過計算導彈、目標和制導站之間的相對位置關系,實現對目標的有效制導。 本文給出MATLAB下的三點法例程,模擬平面上捕獲運動目標的情況訂閱專欄后可直接查看源代碼,粘貼到MATLAB空腳本中即…

Ubuntu22.04 安裝 IsaacSim 4.2.0

1. 從官網下載 IsaacSim 4.2.0 安裝包 https://download.isaacsim.omniverse.nvidia.com/isaac-sim-standalone%404.2.0-rc.18%2Brelease.16044.3b2ed111.gl.linux-x86_64.release.zip 2. 查閱 Workstation Installation 安裝方式 Workstation Installation — Isaac Sim Do…

開源量子模擬引擎:Quantum ESPRESSO本地部署教程,第一性原理計算輕松入門!

一、介紹 Quantum ESPRESSO 是一個用于電子結構計算和納米尺度材料建模的開源計算機代碼集成套件&#xff0c;專門用于進行第一性原理&#xff08;第一性原理&#xff09;計算&#xff0c;涵蓋了電子結構、晶體學和材料性能的模擬。 Quantum ESPRESSO GPU 版本支持GPU加速&am…

PVE 虛擬機安裝 Ubuntu Server V24 系統 —— 一步一步安裝配置基于 Ubuntu Server 的 NodeJS 服務器詳細實錄1

前言 最近在基于 NodeJS V22 寫一個全棧的項目&#xff0c;寫好了&#xff0c;當然需要配置服務器部署啦。這個過程對于熟手來說&#xff0c;還是不復雜的&#xff0c;但是對于很多新手來說&#xff0c;可能稍微有點困難。所以&#xff0c;我把整個過程全部記錄一下。 熟悉我…

【JUC】深入解析 JUC 并發編程:單例模式、懶漢模式、餓漢模式、及懶漢模式線程安全問題解析和使用 volatile 解決內存可見性問題與指令重排序問題

單例模式 單例模式確保某個類在程序中只有一個實例&#xff0c;避免多次創建實例&#xff08;禁止多次使用new&#xff09;。 要實現這一點&#xff0c;關鍵在于將類的所有構造方法聲明為private。 這樣&#xff0c;在類外部無法直接訪問構造方法&#xff0c;new操作會在編譯…

2. 庫的操作

2.1 創建數據庫 語法&#xff1a; CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...] create_specification: [DEFAULT] CHARACTER SET charset_name # 字符集: 存儲編碼 [DEFAULT] COLLATE collation_name # 校驗集: 比較/選擇/讀…

道可云人工智能每日資訊|北京農業人工智能與機器人研究院揭牌

道可云人工智能&元宇宙每日簡報&#xff08;2025年6月3日&#xff09;訊&#xff0c;今日人工智能&元宇宙新鮮事有&#xff1a; 北京農業人工智能與機器人研究院揭牌 5月30日&#xff0c;北京市農業農村局、北京市海淀區人民政府、北京市農林科學院共同主辦北京農業人…

【JSON-to-Video】設置背景視頻片斷

目錄 設置bgVideo字段 1. 設置bgVideo.videoList字段 2. 設置randomPlay字段 3. 設置complete字段 4. 調用API&#xff0c;制作視頻 歡迎來到JSON轉視頻系列教程。今天要教大家如何添加背景視頻片斷&#xff0c;在視頻制作中&#xff0c;巧妙運用背景視頻&#xff0c;能為…

星閃開發之Server-Client 指令交互控制紅燈亮滅案例解析(SLE_LED詳解)

系列文章目錄 星閃開發之Server-Client 指令交互控制紅燈亮滅的全流程解析&#xff08;SLE_LED詳解&#xff09; 文章目錄 系列文章目錄前言一、項目地址二、客戶端1.SLE_LED_Client\inc\SLE_LED_Client.h2.SLE_LED_Client\src\SLE_LED_Client.c頭文件與依賴管理宏定義與全局變…

Linux shell練習題

Shell 1. 判斷~/bigdata.txt 是否存在&#xff0c;若已存在則打印出”該文件已存在“&#xff0c;如不存在&#xff0c;則輸出打印&#xff1a;”該文件不存在“ if [ -f ./bigdata.txt ];then echo "文件存在" else echo "文件不存在" fi2. 判斷~/bigd…

Linux基本指令(三)

接上之前的文章&#xff0c;咱繼續分享Linux的基本指令&#xff0c;Linux指令比較多&#xff0c;很難全部記住需要做筆記對常用的指令進行記錄&#xff0c;方便以后復習查找&#xff0c;做筆記也可以對知識理解更加深刻。 目錄 時間相關指令 date顯示 時間戳 cal指令 ?編…

WebRTC中sdp多媒體會話協議報文詳細解讀

sdp介紹 在WebRTC&#xff08;Web實時通信&#xff09;中&#xff0c;SDP&#xff08;Session Description Protocol&#xff09;是用來描述和協商多媒體會話的協議。它定義了會話的參數和媒體流的信息&#xff0c;如音視頻編碼格式、傳輸方式、網絡地址等。SDP是WebRTC中一個…

【MySQL】 約束

一、約束的定義 MySQL 約束是用于限制表中數據的規則&#xff0c;確保數據的 準確性 和 一致性 。約束可以在創建表時定義&#xff0c;也可以在表創建后通過修改表結構添加。 二、常見的約束類型 2.1 NOT NULL 非空約束 加了非空約束的列不能為 NULL 值&#xff0c;如果可以…

【.net core】【watercloud】樹形組件combotree導入及調用

源碼下載:combotree: 基于layui及zTree的樹下拉框組件 鏈接中提供了組件的基本使用方法 框架修改內容 1.文件導入&#xff08;路徑可更具自身情況自行設定&#xff09; 解壓后將文件夾放在圖示路徑下&#xff0c;修改文件夾名稱為combotree 2.設置路徑&#xff08;設置layu…