算法訓練營day38 動態規劃⑥ 322. 零錢兌換、279.完全平方數、139.單詞拆分、多重背包

????????動態規劃的第六篇!背包問題總結篇!

322. 零錢兌換

????????題目中說每種硬幣的數量是無限的,可以看出是典型的完全背包問題。但是如何找最小的“組合”呢?(通過dp數組的不同定義 與 遞推公式)

  • 確定dp數組以及下標的含義

????????dp[j]:湊足總額為j所需錢幣的最少個數為dp[j]

  • 確定遞推公式

????????湊足總額為j - coins[i]的最少個數為dp[j - coins[i]],那么只需要加上一個錢幣coins[i]即dp[j - coins[i]] + 1就是dp[j]

????????遞推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

  • dp數組如何初始化

????????首先湊足總金額為0所需錢幣的個數一定是0,那么dp[0] = 0;

????????其他下標對應的數值呢?考慮到遞推公式的特性,dp[j]必須初始化為一個最大的數,否則就會在min(dp[j - coins[i]] + 1, dp[j])比較的過程中被初始值覆蓋。

  • 確定遍歷順序

????????本題求錢幣最小個數,那么錢幣有順序和沒有順序都可以,都不影響錢幣的最小個數

  1. 如果求組合數就是外層for循環遍歷物品,內層for遍歷背包
  2. 如果求排列數就是外層for遍歷背包,內層for循環遍歷物品
  • 舉例推導dp數組

????????略

????????以先遍歷物品、后遍歷背包為例

class Solution:def coinChange(self, coins: List[int], amount: int) -> int:dp = [float('inf')] * (amount + 1)  # 創建動態規劃數組,初始值為正無窮大dp[0] = 0  # 初始化背包容量為0時的最小硬幣數量為0for coin in coins:  # 遍歷硬幣列表,相當于遍歷物品for i in range(coin, amount + 1):  # 遍歷背包容量# 注意這個for循環的“剪枝”if dp[i - coin] != float('inf'):  # 如果dp[i - coin]不是初始值,則進行狀態轉移dp[i] = min(dp[i - coin] + 1, dp[i])  # 更新最小硬幣數量if dp[amount] == float('inf'):  # 如果最終背包容量的最小硬幣數量仍為正無窮大,表示無解return -1return dp[amount]  # 返回背包容量為amount時的最小硬幣數量

279.完全平方數

????????題目翻譯一下:完全平方數就是物品(可以無限件使用),湊個正整數n就是背包,問湊滿這個背包最少有多少物品?

  • 確定dp數組(dp table)以及下標的含義

????????dp[j]:和為j的完全平方數的最少數量為dp[j]

  • 確定遞推公式

????????dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以湊成dp[j]。

????????此時我們要選擇最小的dp[j],所以遞推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);

  • dp數組如何初始化

????????dp[0]表示 和為0的完全平方數的最小數量,那么dp[0]一定是0。

????????從遞歸公式dp[j] = min(dp[j - i * i] + 1, dp[j]);中可以看出每次dp[j]都要選最小的,所以非0下標的dp[j]一定要初始為最大值,這樣dp[j]在遞推的時候才不會被初始值覆蓋

  • 確定遍歷順序

????????最小組合,和上題一樣

????????所以本題外層for遍歷背包,內層for遍歷物品,還是外層for遍歷物品,內層for遍歷背包,都是可以的!

  • 舉例推導dp數組

????????略

class Solution:def numSquares(self, n: int) -> int:dp = [float('inf')] * (n + 1)dp[0] = 0for i in range(1, n + 1):  # 遍歷背包for j in range(1, int(i ** 0.5) + 1):  # 遍歷物品 # 注意對j的取值范圍進行開根號的限制# 更新湊成數字 i 所需的最少完全平方數數量dp[i] = min(dp[i], dp[i - j * j] + 1)# 注意這個位置使用的是j * jreturn dp[n]

139.單詞拆分

動態規劃

????????單詞就是物品,字符串s就是背包,單詞能否組成字符串s,就是問物品能不能把背包裝滿。

拆分時可以重復使用字典中的單詞,說明就是一個完全背包!

  • 確定dp數組以及下標的含義

????????dp[i] : 字符串長度為i的話,dp[i]為true,表示可以拆分為一個或多個在字典中出現的單詞

  • 確定遞推公式

????????如果確定dp[j] 是true,且 [j, i] 這個區間的子串出現在字典里,那么dp[i]一定是true。(j < i )。

????????所以遞推公式是 if([j, i] 這個區間的子串出現在字典里 && dp[j]是true) 那么 dp[i] = true。

  • dp數組如何初始化

????????從遞推公式中可以看出,dp[i] 的狀態依靠 dp[j]是否為true,那么dp[0]就是遞推的根基,dp[0]一定要為true,否則遞推下去后面都都是false了。

  • 確定遍歷順序

????????拿 s = "applepenapple", wordDict = ["apple", "pen"] 舉例。

????????"apple", "pen" 是物品,那么我們要求 物品的組合一定是 "apple" + "pen" + "apple" 才能組成 "applepenapple"。

????????"apple" + "apple" + "pen" 或者 "pen" + "apple" + "apple" 是不可以的,那么我們就是強調物品之間順序。

????????所以說,本題一定是 先遍歷 背包,再遍歷物品。

????????換而言之,就是題目中的字符串中單詞元素可能出現在多個位置,所以不能先遍歷物品,不然物品就被消耗掉了,按序遍歷到后面就沒有物品可用了

  • 舉例推導dp[i]

????????略

class Solution:def wordBreak(self, s: str, wordDict: List[str]) -> bool:wordSet = set(wordDict)n = len(s)dp = [False] * (n + 1)  # dp[i] 表示字符串的前 i 個字符是否可以被拆分成單詞dp[0] = True  # 初始狀態,空字符串可以被拆分成單詞for i in range(1, n + 1): # 遍歷背包for j in range(i): # 遍歷單詞if dp[j] and s[j:i] in wordSet:dp[i] = True  # 如果 s[0:j] 可以被拆分成單詞,并且 s[j:i] 在單詞集合中存在,則 s[0:i] 可以被拆分成單詞# 防止被覆蓋breakreturn dp[n]

回溯解法

  • 遞歸終止條件
if startIndex >= len(s):return True
  • 遞歸邏輯
  1. 從 startIndex 開始,嘗試所有可能的拆分位置 i
  2. 截取從 startIndex 到 i 的子串作為候選單詞
  3. 如果這個候選單詞在字典中存在,并且從 i+1 位置開始的剩余字符串也能被成功拆分(遞歸調用的結果為 True),則返回 True
class Solution:def backtracking(self, s: str, wordSet: set[str], startIndex: int) -> bool:# 邊界情況:已經遍歷到字符串末尾,返回Trueif startIndex >= len(s):return True# 遍歷所有可能的拆分位置for i in range(startIndex, len(s)):word = s[startIndex:i + 1]  # 截取子串if word in wordSet and self.backtracking(s, wordSet, i + 1):# 如果截取的子串在字典中,并且后續部分也可以被拆分成單詞,返回Truereturn True# 無法進行有效拆分,返回Falsereturn Falsedef wordBreak(self, s: str, wordDict: List[str]) -> bool:wordSet = set(wordDict)  # 轉換為哈希集合,提高查找效率return self.backtracking(s, wordSet, 0)

多重背包(了解即可)

????????之前我們學了01背包、完全背包,現在我們來看一下多重背包的概念和題目

56. 攜帶礦石資源(第八期模擬筆試)

????????多重背包和01背包是非常像的, 為什么和01背包像呢?每件物品最多有Mi件可用,把Mi件攤開,其實就是一個01背包問題了。

C, N = input().split(" ")
C, N = int(C), int(N)# value數組需要判斷一下非空不然過不了
weights = [int(x) for x in input().split(" ")]
values = [int(x) for x in input().split(" ") if x]
nums = [int(x) for x in input().split(" ")]dp = [0] * (C + 1)
# 遍歷背包容量
for i in range(N):for j in range(C, weights[i] - 1, -1):for k in range(1, nums[i] + 1):# 遍歷 k,如果已經大于背包容量直接跳出循環if k * weights[i] > j:breakdp[j] = max(dp[j], dp[j - weights[i] * k] + values[i] * k) 
print(dp[-1])

背包問題總結篇

背包遞推公式

????????問能否能裝滿背包(或者最多裝多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]); ,對應題目如下:

  • 動態規劃:416.分割等和子集(opens new window)
  • 動態規劃:1049.最后一塊石頭的重量 II(opens new window)

????????問裝滿背包有幾種方法:dp[j] += dp[j - nums[i]] ,對應題目如下:

  • 動態規劃:494.目標和(opens new window)
  • 動態規劃:518. 零錢兌換 II(opens new window)
  • 動態規劃:377.組合總和Ⅳ(opens new window)
  • 動態規劃:70. 爬樓梯進階版(完全背包)(opens new window)

????????問背包裝滿最大價值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); ,對應題目如下:

  • 動態規劃:474.一和零(opens new window)

????????問裝滿背包所有物品的最小個數:dp[j] = min(dp[j - coins[i]] + 1, dp[j]); ,對應題目如下:

  • 動態規劃:322.零錢兌換(opens new window)
  • 動態規劃:279.完全平方數

遍歷順序

  • 01背包:

????????一維dp數組的背包在遍歷順序上和二維dp數組實現的01背包其實是有很大差異的

  • 完全背包

????????題目稍有變化,兩個for循環的先后順序就不一樣了。相關題目如下:

  1. 如果求組合數就是外層for循環遍歷物品,內層for遍歷背包
  2. 如果求排列數就是外層for遍歷背包,內層for循環遍歷物品
  • 求組合數:動態規劃:518.零錢兌換II(opens new window)

  • 求排列數:動態規劃:377. 組合總和 Ⅳ?(opens new window)、動態規劃:70. 爬樓梯進階版(完全背包)(opens new window)

????????如果求最小數,那么兩層for循環的先后順序就無所謂了,相關題目如下:

  • 求最小數:動態規劃:322. 零錢兌換?(opens new window)、動態規劃:279.完全平方數

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

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

相關文章

vue+element 實現下拉框共享options

背景 用戶的需求總是多樣的&#xff0c;這不用戶想做個下拉連選&#xff0c;每選一個基金&#xff0c;下方表格多一行&#xff0c;選擇對應的重要性&#xff0c;任務&#xff1b;問題 其他都好弄&#xff0c;任務是遠程搜索&#xff0c;選擇人的單選下拉&#xff0c;如果每個下…

centos服務器安裝minio

1.創建目錄和下載文件 #創建相關文件夾 mkdir -p /home/minio mkdir -p /home/minio/bin mkdir -p /home/minio/data#進入上面創建的bin目錄下 cd /home/minio/bin#下載minio&#xff08;最新版minio無法通過頁面的控制臺配置accesskey建議選擇2024年的版本操作&#xff09; ht…

【云故事探索】NO.16:阿里云彈性計算加速精準學 AI 教育普惠落地

智能精準學寒雪老師 X 阿里云彈性計算&#xff1a;以堅實算力底座&#xff0c;實現 AI 一對一教育普惠的愿景 【導語】 當全球首個 K12 教育超級智能體“寒雪老師”在深夜為萬千學子答疑解惑&#xff0c;支撐其流暢互動的&#xff0c;是阿里云彈性計算 15 年淬煉的堅實算力底座…

forge篇——配置

從這篇文章開始,我們開始研究forge代碼,以下是forge源代碼和代碼解析 ForgeConfigSpec 類詳細解析 ForgeConfigSpec 是 Minecraft Forge 模組開發中的核心配置類,基于 NightConfig 庫實現,提供了類型安全、驗證和自動糾正功能。以下是關鍵部分的詳細解釋: 1. 類定義與基…

全新發布|知影-API風險監測系統V3.3,AI賦能定義數據接口安全新坐標

7月31日&#xff0c;全知科技「知影-API風險監測系統V3.3」版本正式上線。在版本發布直播中&#xff0c;全知科技資深產品經理裴向南系統講解了V3.3版本的核心亮點、能力升級與后續產品規劃方向。作為全知科技自主研發的核心產品&#xff0c;「知影-API風險監測系統」自2017年起…

動作捕捉技術重塑具身智能開發:高效訓練與精準控制的新范式

具身智能&#xff08;Embodied AI&#xff09;是指智能體通過與環境交互實現感知、學習和決策的能力&#xff0c;其核心在于模擬人類或生物的形態與行為。具身智能的發展意義在于突破傳統AI的局限性&#xff0c;使機器能夠適應復雜多變的真實場景&#xff0c;從而在工業制造、醫…

【Andriod Studio】勾選不了Android SDK,提示unavailable

首先&#xff0c;直接說結論——網絡&#xff08;代理&#xff09;有問題 先看第一個文章里面說的&#xff0c;https://blog.csdn.net/weixin_53485880/article/details/128200878 要確定自己沒有開啟代理&#xff08;就是Set proxy里選cancel&#xff09;&#xff0c;安裝SDK…

數據結構與算法——字典(前綴)樹的實現

參考視頻&#xff1a;左程云--算法講解044【必備】前綴樹原理和代碼詳解 類實現&#xff1a; class Trie {private:class TrieNode {public:int pass;int end;vector<TrieNode*> nexts;TrieNode(): pass(0), end(0), nexts(26, nullptr) {}};TrieNode* root; // 根指針…

STORM代碼閱讀筆記

默認的 分辨率是 [160,240] &#xff0c;基于 Transformer 的方法不能做高分辨率。 Dataloader 輸入是 帶有 pose 信息的 RGB 圖像 eval datasets ## 采樣幀數目 20 num_max_future_frames int(self.timespan * fps) ## 每次間隔多少個時間 timesteps 取一個context image n…

2025電賽G題-發揮部分-參數自適應FIR濾波器

&#xff08;1&#xff09;測評現場提供由RLC元件&#xff08;各1個&#xff09;組成的“未知模型電路”。 按照圖3所示&#xff0c;探究裝置連接該電路的輸入和輸出端口&#xff0c;對該電路進行 自主學習、建模&#xff08;不可借助外部測試設備&#xff09;&#xff0c;2分鐘…

Linux基礎 -- 內核快速向用戶態共享內核變量方案之ctl_table

系統化、可直接上手的 /proc/sys sysctl 接口使用文檔。內容涵蓋&#xff1a;機制原理、適用場景、ctl_table 字段詳解、常用解析器&#xff08;proc_handler&#xff09;完整清單與選型、最小樣例到進階&#xff08;范圍校驗、毫秒→jiffies、字符串、數組、每網絡命名空間&a…

【RH124知識點問答題】第3章 從命令行管理文件

1. 怎么理解“Linux中一切皆文件”&#xff1f;Linux是如何組織文件的&#xff1f;&#xff08;1&#xff09;“Linux中一切皆文件”的理解和文件組織&#xff1a;在Linux中&#xff0c;“一切皆文件”指的是Linux將各種設備、目錄、文件等都視為文件對象進行管理。這種統一的文…

練習javaweb+mysql+jsp

只是簡單的使用mysql、簡單的練習。 有很多待完善的地方&#xff0c;比如list的servlet頁面&#xff0c;應該判斷有沒有用戶的。 比如list.jsp 應該循環list而不是寫死 index.jsp 樣式可以再優化一下的。比如按鈕就特丑。 本文展示了一個簡單的MySQL數據庫操作練習項目&#x…

使用Nginx部署前端項目

使用Nginx部署前端項目 一、總述二、具體步驟 2.1解壓2.2將原來的html文件夾的文件刪除&#xff0c;將自己的靜態資源文件放進去&#xff0c;點擊nginx.exe文件啟動項目2.3查看進程中是否有ngix的兩個進程在瀏覽器中輸入“localhost:端口號”即可訪問。 2.4端口被占用情況處理 …

【論文學習】KAG論文翻譯

文章目錄KAG: Boosting LLMs in Professional Domains via Knowledge Augmented Generation摘要1 引言2 方法論2.1 LLM友好型知識表示2.2 互索引機制2.2.1 語義分塊2.2.2 帶豐富語境的的信息抽取2.2.3 領域知識注入與約束2.2.4 文本塊向量與知識結構的相互索引2.3 邏輯形式求解…

24黑馬SpringCloud安裝MybatisPlus插件相關問題解決

目錄 一、前言 二、菜單欄沒有Other 三、Config Database里的dburl需要加上時區等配置 一、前言 在學習24黑馬SpringCloud的MybatisPlus-12.拓展功能-代碼生成器課程時&#xff0c;發現由于IDEA版本不同以及MybatisPlus版本更新會出現與視頻不一致的相關問題&#xff0c;本博…

人工智能賦能聚合物及復合材料模型應用與實踐

近年來&#xff0c;生成式人工智能&#xff08;包括大語言模型、分子生成模型等&#xff09;在聚合物及復合材料領域掀起革命性浪潮&#xff0c;其依托數據驅動與機理協同&#xff0c;從海量數據中挖掘構效關系、通過分子結構表示&#xff08;如 SMILES、BigSMILES&#xff09;…

MyBatis-Plus3

一、條件構造器和常用接口 1.wapper介紹 MyBatis-Plus 提供了一套強大的條件構造器&#xff08;Wrapper&#xff09;&#xff0c;用于構建復雜的數據庫查詢條件。Wrapper 類允許開發者以鏈式調用的方式構造查詢條件&#xff0c;無需編寫繁瑣的 SQL 語句&#xff0c;從而提高開…

GXP6040K壓力傳感器可應用于醫療/汽車/家電

GXP6040K 系列壓力傳感器是一種超小型&#xff0c;為設備小型化做出貢獻的高精度半導體壓力傳感器&#xff0c;適用于生物醫學、汽車電子、白色家電等領域。采用標準的SOP6 和 DIP6 封裝形式&#xff0c;方便用戶進行多種安裝方式。 內部核心芯片是利用 MEMS&#xff08;微機械…

Android ConstraintLayout 使用詳解

什么是 ConstraintLayoutConstraintLayout&#xff08;約束布局&#xff09;是 Android Studio 2.2 引入的一種新型布局&#xff0c;現已成為 Android 開發中最強大、最靈活的布局管理器之一。它結合了 RelativeLayout 的相對定位和 LinearLayout 的線性布局優勢&#xff0c;能…