基礎算法篇(5)(藍橋杯常考點)—動態規劃(C/C++)

文章目錄

  • 動態規劃
    • 前言
    • 線性dp
    • 路徑類dp
    • 經典線性dp
    • 背包問題分類
    • 01背包問題
    • 完全背包問題
    • 多重背包
    • 分組背包問題
    • 混合背包問題
    • 多維費用的背包問題
    • 區間dp

動態規劃

前言

在競賽中,如果遇到動態規劃的題目,只要不是經典題型,那么大概率就是以壓軸題的形式出現

用動態規劃解決問題的步驟:(遞推形式)

1.定義狀態表示:

根據經驗+需要的意義,賦予dp數組相應的含義

(主要還是看需要記什么)

2.推導狀態轉移方程:

在dp表中分析,當前格子如何通過其余格子推導出來的

3.初始化:

將顯而易見的以及邊界情況下的位置填上值,來讓后續填表的結果是正確的

4.確定填表順序:

根據狀態轉移方程,確定按照什么順序來填表

5.找出最終結果:

在表中找出需要的最終結果

洛谷 P10250 [GESP樣題 六級] 下樓梯
洛谷 P1216 [USACO1.5] [IOI1994]數字三?形 Number Triangles

動態規劃常要空間優化:
即把不用了的值給不要了
但是背包問題如果不能用1個數組優化,而要多個數組的話,那就不空間優化了,否則可能會超時
常見的優化方法:
方法一:一維轉幾個數
例題:洛谷   P10250 [GESP樣題 六級] 下樓梯方法二:二維轉一維
1.是否需要修改遍歷順序
2.刪掉一維即可
例題:洛谷  P1216 [USACO1.5] [IOI1994]數字三?形 Number Triangles

洛谷 P1115 最??段和
洛谷 P1541 [NOIP2010 提?組] 烏?棋

一些技巧:
1.狀態表示:
a.研究子數組或子序列問題時,從某個位置結尾來定義狀態表示 例:洛谷 P1115 最??段和
b.優化問題:有一維可以由其他維的數據推出的話,可以不要這一維(不是指那個空間優化方法)例題:洛谷  P1541 [NOIP2010 提?組] 烏?棋2.狀態轉移方程:
a.求方案數一般是相加
b.常從最后一步開始分析去推導狀態轉移方程3.初始化:
在求方案數時,一般將第一個位置初始化為1,其他位置為0

線性dp

特點:狀態轉移只依賴于前一個或前幾個狀態;狀態之間的關系是線性的

路徑類dp

洛谷 P1004 [NOIP2000 提?組] ?格取數

走兩次的得到的值之和最大問題:
(兩次的規則要一樣,走到不同位置的得到的值不一樣,且每位置的值只能得一次)
例題:洛谷  P1004 [NOIP2000 提?組] ?格取數
在狀態表示時:兩者如果是同時出發的(非同步則要改一點),其橫縱坐標之和會是一個定值
一般表示為f[st][i1][i2]:
意思是:第一條路在[i1,st-i1],第二條路在[i2,st-i2]時,兩者的路徑(取數)之和最大

經典線性dp

經典線性dp問題有兩個:最長上升子序列和最長公共子序列

這兩道題的解題思路,定義狀態表示方式和推導狀態轉移方程的技巧常被用到其他題目中去

洛谷 B3637 最?上升?序列
洛谷 P1091 [NOIP2004 提?組] 合唱隊形

最長上升子序列(數據范圍小時用此)
時間復雜度是O(n平方)
鏈接:洛谷  B3637 最?上升?序列
要理解最長上升子序列是什么意思!!!
1.狀態表示:
dp[i]表示:以i位置為結尾的所有子序列中,最長遞增子序列的長度
2.狀態轉移方程:
根據子序列的構成方式進行分類討論:第一種:子序列長度為1:此時的dp[i] = 1;
第二種: 子序列的長度大于1:設j為前面某一個數的下標
只要a[j]<a[i],i位置元素跟在j元素后面就可以形成遞增序列
其dp[i] = max(dp[j]+1p,dp[i])
3.初始化:
每次填表的時候,先把這個位置的數改成最小的域值即可主要部分的代碼展示:
int ret = 0;
for(int i=1;i<=n;i++)
{ 
dp[i]=1;
for(int j=1;j<i;j++){if(a[j]<a[i])dp[i] = max(dp[i],dp[j]+1); }ret = max(ret,dp[i])
}應用: 洛谷  P1091 [NOIP2004 提?組] 合唱隊形

牛客網 【模板】最?上升?序列

最長上升子序列(數據范圍大時用此)
時間復雜度時O(n*logn)
鏈接:牛客網 【模板】最?上升?序列
優化動態規劃:
1.發現在考慮最長遞增子序列長度時,只用關心現在長度和序列最后一個元素
因此僅需統計長度為x的所有遞增序列中最后一個元素的最小值(創建數組去統計)
2.在統計過程中發現:
數組中的數呈現遞增趨勢,因為可以使用二分來查找插入位置
主要部分的代碼展示:
for(int i =1;i<=n;i++)
{//處理邊界情況if(len ==0||a[i]>f[len]) f[++len]=a[i];
else{//二分插入位置int l = 1,r = len;while(l<r){int mid = (l+r)/2;if(f[mid]>=a[i]) r = mid;else l =mid+1;}f[l] = a[i]} }

牛客網 ?可樂和最?公共?序列
洛谷 P2758 編輯距離

牛可樂和最長公共子序列
鏈接:牛客網  ?可樂和最?公共?序列
1.狀態表示:
dp[i][j]表示:
s1的[1,i]區間以及s2的[1,j]區間內的所有的子序列中,最長公共子序列的長度2.狀態轉移方程:
對于dp[i][j],我們可以根據s1[i]與s2[j]的字符分情況討論:
第一種:兩個字符相同 dp[i][j] = dp[i-1][j-1]+1
第二種:兩個字符不同 有以下三種策略
a.去s1的[1,i-1]以及s2的[1,j]區間內找:此時最大長度為dp[i-1][j]
b.去s1的[1,i]以及s2的[1,j-1]區間內找:此時最大長度為dp[i][j-1]
c.去s1的[1,i-1]以及s2的[1,j-1]區間內找:此時最大長度為dp[i-1][j-1]
(發現c包含在a和b情況里)
然后要a,b中的最大值即可代碼展示:
for(int i =1;i<=n;i++)
{for(int j = 1;j<=m;j++){if(s[i-1] == t[j-1])f[i][j] = f[i-1][j-1]+1;else f[i][j] = max(f[i-1],f[i][j-1])}}應用:洛谷  P2758 編輯距離

背包問題分類

01背包問題:沒中物品只能選或不選(選0次或1次)

完全背包問題:每種物品可以選擇無限次

多重背包問題:每種物品有數量限制

分治背包問題:物品被分為若干組,每組只能選一個物品

混合背包:以上四種背包問題混在一起

多維費用的背包問題:限定條件不止有體積,還會有其他因素(比如重量)

背包問題的三種限定情況:
1.體積不超過j->小于等于j->j>=v[i]
2.體積正好為j->恰好等于j->要判斷f表中某些狀態是否合法
3.體積至少為j->大于等于j->j<v[i]也是合法的,映射到0位置即可背包問題在求方案數時,要把不選的情況單獨寫出,然后從只選一個開始,不然套模板可能會錯
例:洛谷  P1077 [NOIP2012 普及組] 擺花

洛谷 P1077 [NOIP2012 普及組] 擺花

01背包問題

牛客網 【模板】01背包
洛谷 P2946 [USACO09MAR] Cow Frisbee Team S

01背包中的最大價值問題:
模板題:牛客網 【模板】01背包
v[i]表示第i個的體積   w[i]表示第i個的價值
第一問:求這個背包至多能裝多大價值的物品1.狀態表示:
dp[i][j]表示:從前i個物品中挑選,總體積不超過j,所有的選法中,能挑選出來的最大價值
那么dp[n][v]就是我們要的結果
2.狀態轉移方程:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i])
3.初始化:無
4.填表順序:從上往下(二維一般都是從上往下)  從右往左代碼表現:
for(int i = 1;i<=n;i++)
{ for(int j=0;j<=m;j++){f[i][j] = f[i-1][j];if(j>=v[i])f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);}
}
空間優化版:(熟練了之后,直接寫此)for(int i = 1;i<=n;i++)
{ for(int j=m;j>=v[i];j--)//01背包空間優化要修改遍歷順序{f[j] = max(f[j],f[j-v[i]]+w[i]);}
}第二問:
若背包恰好裝滿,求至少能裝多大價值
僅需要在第一問基礎上修改一下初始化以及最終結果即可
1.初始化
把所有位置先設置成-0x3f3f3f3f;然后把dp[0][0]修改成0
2.最終結果
要多一步判斷最后一個位置是不是小于0代碼展現:
memset(f,-0x3f,sizeof f);//多了這個
for(int i = 1;i<=n;i++)
{ for(int j=0;j<=m;j++){f[i][j] = f[i-1][j];if(j>=v[i])f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);}
}
if(f[n][m]<0)cout<<0<<endl;//多了這個
else cout << f[n][m]<<endl;//多了這個
空間優化版:(熟練了之后,直接寫此)
memset(f,-0x3f,sizeof f);for(int i = 1;i<=n;i++)
{ for(int j=m;j>=v[i];j--)//01背包空間優化要修改遍歷順序{f[j] = max(f[j],f[j-v[i]]+w[i]);}
}
if(f[m]<0)cout<<0<<endl;
else cout << f[m]<<endl;注意:有些題可能不能用這種空間優化,因為要用到之前的數據的多少不同了
例題:洛谷  P2946 [USACO09MAR] Cow Frisbee Team S
(這題還要注意的是狀態表示不能搞能力值總和為j,要搞總和模之后為j,不然空間時間都易超)

洛谷 P1164 ?A點菜

01背包中的方案數問題:
題目鏈接:洛谷  P1164 ?A點菜
1.狀態表示:
dp[i][j]表示:從前i個菜中挑選,總價錢恰好等于j,此時的總方案數
2.針對于a[i]選或不選,分兩種情況討論:
得:dp[i][j] = d[i-1][j]+d[i-1][j-a[i]]
注意第二個狀態可能不存在,要注意判斷一下j>=a[i]
3.初始化:
dp[0][0] = 1

完全背包問題

牛客網 【模板】完全背包

模板題:牛客網 【模板】完全背包
第一問:求這個背包至多能裝多大價值的物品
1.狀態表示:和01背包一樣
2.狀態轉移方程:
dp[i][j] = max(dp[i-1][j],dp[i][j-v[i]]+w[i])
3.初始化:
從第二行開始存,第一行全初始化為0
4.沒有空間優化時,是從上往下,從左往右第二問:若背包恰好裝滿,求至多能裝多大價值的物品
改法跟01背包那里完全相同與01背包的不同點:在空間優化時,完全背包的遍歷順序還是從左往右

多重背包

牛客網 多重背包

例題: 牛客網  多重背包
小tip:不是所有的多重背包問題都能用二進制優化,而且優化版本的代碼很長如果時間復雜度允許的情況下,能不優化就不優化
解法一:
1.狀態表示:
dp[i][j]表示:
從前i個物品中挑選,總重量不超過j的情況下,最大的價值2.狀態轉移方程:
這里不能用完全背包的方式(不是指那個空間優化)去優化
只能硬分x[i]+1種情況(選0個到選x[i]個)
選x[i]個:價值為dp[i-1][j-x[i]*w[i]]+x[i]*v[i] 3.初始化:
全部初始化為04.填表順序:
從上往下,從左往右
空間優化之后則是從右往左代碼展現:
for(int i =1;i<=n;i++)for(int j= m;j>=0;j--)for(int k = 0;k<=x[i]&&k*w[i]<=j;k++)f[j] = max(f[j],f[j-k*w[i]]+k*v[i])解法二:轉化為01背包問題
優化方式:用二進制將同種的x[i]個物品分組
(如果是求方案數的話,是不能用二進制去優化的,會多算幾種)
把這x[i]個物品拆成一些二進制數再加上多出來的數此題的有100種不同物品的話
如果同種的物品最多能分成5份,則數組的N要取(100+10)*5//+10純屬個人習慣

洛谷 P1077 [NOIP2012 普及組] 擺花

多重背包的方案數問題:
例題:洛谷  P1077 [NOIP2012 普及組] 擺花
也就狀態轉移方程和初始化改了一下

分組背包問題

洛谷 P1757 通天之分組背包

例題:洛谷  P1757 通天之分組背包
1.狀態表示:
dp[i][j]表示從前i組中挑選物品,總重量不超過j的情況下,最大的價值2.狀態轉移方程:
根據第i組選什么物品,可以分若干情況討論
這個在空間優化時,第二維也要從右到左

混合背包問題

洛谷 P1833 櫻花

例題:洛谷 P1833 櫻花
這個混合背包的話,分情況討論是哪種背包就是
注意的點是:多重背包和01背包的代碼具有可合并性

多維費用的背包問題

洛谷 P1910 L 國的戰?之間諜

例題:洛谷  P1910 L 國的戰?之間諜
這無非就是多加幾維就行
eg:
狀態表示:
dp[i][j][k]表示:
從前i個人中挑選,偽裝能力不超過j,總工資不超過k,此時能獲取到的最多資料總數
eg:像這種獲取到的最多資料總數,能砍到的最多的樹木這種一般不為限制條件,一般是所求的值
在空間優化時,也只能優化掉第一維(從前i個人中挑選--這個一般放第一維)
空間優化后,除了第一維的遍歷順序可能都需要發生變化

區間dp

區間dp是用區間的左右端點來描述狀態,通過小區間的解來推導出大區間的解

核心思想:將大區間劃分為小區間,其狀態轉移方程通常依賴于區間的劃分點

常見的劃分點的方式有兩個:

1.基于區間的左右端點,分情況討論

2.基于區間上的某一個點,劃分成左右區間討論

應用:在序列中只關心左右兩端,大概率用區間dp

洛谷 P1435 [IOI2000] 回?字串

例題:洛谷  P1435 [IOI2000] 回?字串
1.狀態表示:
dp[i][j]表示:
字符串[i,j]區間,變成回文串的最小插入次數
那么,dp[1][n]就是我們要的結果2.狀態轉移方程:
根據區間的左右端點,分情況討論對于區間dp的填表順序,一般用的是:
第一維循環:從小到大枚舉區間長度len;第二維循環:枚舉區間左端點i,然后計算出區間右端點j
j = i+len-1 
這個len有時從1開始,有時從2開始,看題
eg:
for(int len = 1;len<=n;len++)for(int i = 1; i+len-1<=n;i++)

洛谷 P2858 [USACO06FEB] Treats for the Cows G/S
洛谷 P3146 [USACO16OPEN] 248 G

關于這里的狀態轉移方程:
1.如果劃分點是基于區間的左右端點,分情況討論
eg: 洛谷  P2858 [USACO06FEB] Treats for the Cows G/S先拿左邊,然后去[i + 1, j] 區間獲得最多的錢,
即a[i] × (n ? len + 1) + dp[i + 1][j] 先拿右邊,然后去[i,j-1]區間獲得最多的錢
即a[j]*(n-len+1)+de[i][j-1]2.如果劃分點是基于區間上的某一個點,劃分成左右區間討論
eg: 洛谷    P3146 [USACO16OPEN] 248 G根據最后一次合并的情況,可以把區間分成[i,k][k+1,j](劃分點是k)

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

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

相關文章

obsidian寫文章的圖床設置方法

目標 要達成的需求&#xff1a; 復制到obsidian的圖片&#xff0c;自動上傳到Picgo配置的圖床。可以自定義大小。可以一鍵下載當前文章的圖片到本地。 obsidian配置圖床 安裝并配置插件 image auto upload plugin&#xff0c;配置信息如下圖。 滾輪alt自定義大小 安裝并…

QPaintDevice繪圖設備

1.QPixmap 對不同平臺做了顯示的優化&#xff0c;可以將畫的圖保存到磁盤上 頭文件&#xff1a; #include"QPixmap" #include"QPainter" 1.1QPixmap畫圖 代碼&#xff1a; //Pixmap繪圖設備QPixmap pix(300,300);//聲明畫家QPainter painter(&pix…

數據結構有哪些類型(對于數據結構的簡述)

在學習計算機時&#xff0c;數據結構是不可忽視的一點&#xff0c;從考研時的408課程&#xff0c;再到工作中編寫軟件&#xff0c;網站&#xff0c;要想在計算機領域站住腳跟&#xff0c;數據結構是必備的 在這里&#xff0c;我對于數據結構進行了匯總&#xff0c;并簡要描述&…

L2TP實驗(無圖后補)

拓撲圖 一、搭建拓撲并配置基礎 IP 地址 設備選型與拓撲搭建&#xff1a;在 eNSP 中&#xff0c;拖入所需設備&#xff0c;包括 LAC&#xff08;L2TP Access Concentrator&#xff0c;L2TP 接入集中器 &#xff09;、LNS&#xff08;L2TP Network Server&#xff0c;L2TP 網絡服…

【C#】CAN通信的使用

在C#中實現CAN通信通常需要借助第三方庫或硬件設備的驅動程序&#xff0c;因為C#本身并沒有直接內置支持CAN通信的功能。以下是一個關于如何使用C#實現CAN通信的基本指南&#xff0c;包括所需的步驟和常用工具。 1. 硬件準備 要進行CAN通信&#xff0c;首先需要一個支持CAN協…

02_C++入門案例習題while循環練習案例:猜數字

案例描述&#xff1a;系統隨機生成一個1到100之間的數字&#xff0c;玩家進行猜測&#xff0c;如果猜錯&#xff0c;提示玩家數字過大或過小&#xff0c;如果猜對恭喜玩家勝利&#xff0c;并且退出游戲。 需要引入隨機數種子 #include <cstdlib> #include <ctime>…

深入理解哈希沖突:原理、解決方案及 Java 實踐

概述&#xff1a;在計算機科學領域&#xff0c;哈希表是一種非常重要的數據結構&#xff0c;它通過哈希函數將鍵映射到存儲桶中&#xff0c;從而實現快速的數據查找、插入和刪除操作。然而&#xff0c;哈希表在實際應用中會面臨 哈希沖突的問題。本文將深入探討哈希沖突的原理、…

opencv(C++)處理圖像顏色

文章目錄 介紹使用策略設計模式比較顏色實現方案計算兩個顏色向量之間的距離1. 簡單方法&#xff1a;曼哈頓距離計算&#xff08;Manhattan Distance&#xff09;2.使用 OpenCV 的 cv::norm 函數3.使用 OpenCV 的 cv::absdiff 函數錯誤示例 使用 OpenCV 函數實現顏色檢測實現方…

DOM解析XML:Java程序員的“樂高積木式“數據搭建

各位代碼建筑師們&#xff01;今天我們要玩一個把XML變成內存樂高城堡的游戲——DOM解析&#xff01;和SAX那種"邊看監控邊破案"的刺激不同&#xff0c;DOM就像把整個樂高說明書一次性倒進大腦&#xff0c;然后慢慢拼裝&#xff08;內存&#xff1a;你不要過來啊&…

Apache Nifi安裝與嘗試

Apache NIFI中文文檔 地址&#xff1a;https://nifichina.github.io/ 下載安裝配置 1、環境準備 Nifi的運行需要依賴于java環境&#xff0c;所以本機上需要安裝java環境&#xff0c;并配置環境變量。 1.1查看本機是否已經存在java環境 請先執行以下命令找出系統中真實可用…

我可能用到的網站和軟件

我可能用到的網站和軟件 程序員交流的網站代碼管理工具前端組件庫前端框架在線工具人工智能問答工具學習的網站Windows系統電腦的常用工具 程序員交流的網站 csdn博客博客園 - 開發者的網上家園InfoQ - 軟件開發及相關領域-極客邦掘金 (juejin.cn) 代碼管理工具 GitHub 有時…

使用SSH解決在IDEA中Push出現403的問題

錯誤截圖&#xff1a; 控制臺日志&#xff1a; 12:15:34.649: [xxx] git -c core.quotepathfalse -c log.showSignaturefalse push --progress --porcelain master refs/heads/master:master fatal: unable to access https://github.com/xxx.git/: The requested URL return…

JavaScript異常機制與嚴格模式

目錄 JavaScript 異常機制 1. 基本語法&#xff1a;try...catch...finally 2. 拋出異常&#xff1a;throw 3. 錯誤對象屬性 4. 同步代碼的異常處理 5. 異步代碼的異常處理 5.1 回調函數 5.2 Promise 5.3 全局未捕獲的 Promise 錯誤 6. 全局錯誤處理 7. 自定義錯誤與…

中廠算法崗面試總結

時間&#xff1a;2025.4.10 地點&#xff1a;上市的電子有限公司 面試流程&#xff1a; 1.由負責人講解公司文化 2&#xff0c;由技術人員講解公司的技術崗位&#xff0c;還有成果 3.帶領參觀各個工作位置&#xff0c;還有場所 4.中午吃飯 5.面試題&#xff0c;閉卷考試…

vue+flask圖書知識圖譜推薦系統

文章結尾部分有CSDN官方提供的學長 聯系方式名片 文章結尾部分有CSDN官方提供的學長 聯系方式名片 關注B站&#xff0c;有好處&#xff01; 編號: F025 架構: vueflaskneo4jmysql 亮點&#xff1a;協同過濾推薦算法知識圖譜可視化 支持爬取圖書數據&#xff0c;數據超過萬條&am…

MySQL NDB Cluster詳解

MySQL NDB Cluster&#xff08;MNC&#xff09; 是MySQL提供的一種分布式數據庫解決方案&#xff0c;旨在提供高可用性、高性能的數據庫服務。它通過 NDB&#xff08;Network DataBase&#xff09; 存儲引擎實現了高可用性和分布式存儲&#xff0c;在NDB中&#xff0c;數據通過…

解決華碩主板Z890m下載ubuntu20.04后沒有以太網問題

問題描述&#xff1a; 華碩主板Z890m下載雙系統ubuntu20.04后&#xff0c;發現ubuntu不能打開以太網。 問題原因&#xff1a; 華碩主板的網卡驅動是r8125,而ubuntu20.04的驅動版本是r8169&#xff0c;所以是網卡驅動不匹配造成 解決方案 開機界面按下F2進入BOIS模式&#…

JS里對于集合的簡單介紹

JS的集合 前言一、集合二、基本使用1. 創建集合2. 添加元素3. 刪除元素4. 檢查元素5. 清空集合6. 集合的大小 三、擴展使用1. 遍歷集合2. 從數組創建集合3. 集合的應用場景 四、總結 前言 JS里對于集合的簡單介紹 同數學的集合&#xff0c;有無序性、唯一性 注意&#xff1a;…

pytorch 反向傳播

文章目錄 概念計算圖自動求導的兩種模式 自動求導-代碼標量的反向傳播非標量變量的反向傳播將某些計算移動到計算圖之外 概念 核心&#xff1a;鏈式法則 深度學習框架通過自動計算導數(自動微分)來加快求導。 實踐中&#xff0c;根據涉及號的模型&#xff0c;系統會構建一個計…

Kotlin日常使用函數記錄

文章目錄 前言字符串集合1.兩個集合的差集2.集合轉數組2.1.集合轉基本數據類型數組2.2.集合轉對象數組 Map1.合并Map1.1.使用 操作符1.2.使用 操作符1.3.使用 putAll 方法1.4.使用 merge 函數 前言 記錄一些kotlin開發中&#xff0c;日常使用的函數和方式之類的&#xff0c;…