Day37--動態規劃--52. 攜帶研究材料(卡碼網),518. 零錢兌換 II,377. 組合總和 Ⅳ,57. 爬樓梯(卡碼網)

Day37–動態規劃–52. 攜帶研究材料(卡碼網),518. 零錢兌換 II,377. 組合總和 Ⅳ,57. 爬樓梯(卡碼網)

本文全部都是 ” 完全背包 “ 問題,從零到入坑,從入坑到爬出來。

本文的精華在:《為什么是“先遍歷背包,后遍歷數字”?》非常詳細地講解了,為什么先遍歷數字,后遍歷背包——是組合數。先遍歷背包,后遍歷數字——是排列數。

52. 攜帶研究材料(卡碼網)

思路:

  1. 確定dp數組含義:dp[i][j] 表示從下標為[0-i]的物品,每個物品可以取無限次,放進容量為j的背包,價值總和最大是多少
  2. 確定遞推公式:(和01背包相似,所以只講區別)
    • 在01背包中,每個物品只有一個,既然空出物品1,那背包中也不會再有物品1。所以空出來之后,去上一層找,即dp[i-1][j-weight[i]]
    • 而在完全背包中,每個物品可以無限取,即使空出物品1空間重量,那背包中也可能還有物品1。所以空出來之后,要從本層取,即dp[i][j-weight[i]]
    • 得出遞推公式:dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - weight[i]] + value[i]);
  3. 初始化:初始化第一行,從背包能放得下weight[0]這個東西開始,往后遍歷。能放多少是多少。
  4. 確定遍歷順序,每個dp[i][j],都要靠左邊,上邊的值確定數據。所以是從上往下,從左往右。
import java.util.*;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int bagSize = in.nextInt();int[] weight = new int[n];int[] value = new int[n];for (int i = 0; i < n; i++) {weight[i] = in.nextInt();value[i] = in.nextInt();}int[][] dp = new int[n][bagSize + 1];// 初始化第一行,從背包能放得下weight[0]這個東西開始,往后遍歷for (int j = weight[0]; j <= bagSize; j++) {dp[0][j] = dp[0][j - weight[0]] + value[0];}// 動態規劃for (int i = 1; i < n; i++) {for (int j = 1; j <= bagSize; j++) {// 當前背包放不下weight[i],直接等于上一層if (j < weight[i]) {dp[i][j] = dp[i - 1][j];} else {// 這里的遞歸公式,與01背包不同。要空出weight[i]的時候,看的是本層的dp// 區別在于,這里是dp[i][j - weight[i]],而01背包是:dp[i-1][j - weight[i]]dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - weight[i]] + value[i]);}}}System.out.println(dp[n - 1][bagSize]);}
}

518. 零錢兌換 II

思路:二維dp數組

  1. 確定dp[i][j]含義,從0-i的coins中,任選一個或多個,裝滿容量為j的背包(注意是裝滿)
  2. 確定遞推公式:
    1. 注意這里求的是“最大組合數”,而不是“最大價值”,所以是加法(情況一+二)
    2. 情況一,不放coins[i],就是dp[i-1][j],情況二,放coins[i],就是dp[i][j-coins[i]]
    3. 注意這里不是[i-1]了,是[i]。不是看上層的,而是看本層的,這是完全背包和01背包的關鍵區別
  3. 初始化
    1. 初始化第一列:都有“不選”的選擇,所以是1
    2. 初始化第一行:要能取模的才能賦值1,比如最小貨幣是2的話,當j==3,是不能裝滿的
// 確定dp[i][j]含義,從0-i的coins中,任選一個或多個,裝滿容量為j的背包
class Solution {public int change(int amount, int[] coins) {// amount 是 bagSizeint n = coins.length;int[][] dp = new int[n][amount + 1];// 初始化第一列for (int i = 0; i < n; i++) {// 都有“不選”的選擇,所以是1dp[i][0] = 1;}// 初始化第一行for (int j = coins[0]; j <= amount; j++) {// 特別注意,要能取模的才能賦值1,比如最小貨幣是2的話,當j==3,是不能裝滿的if (j % coins[0] == 0) {dp[0][j] = 1;}}// 動態規劃for (int i = 1; i < n; i++) {for (int j = 1; j <= amount; j++) {// 當前硬幣大于背包容量,直接等于上一層if (j < coins[i]) {dp[i][j] = dp[i - 1][j];} else {// 注意這里求的是“最大組合數”,而不是“最大價值”,所以是加法(情況一+二)// 情況一,不放coins[i],就是dp[i-1][j]// 情況二,放coins[i],就是dp[i][j-coins[i]]// 注意這里不是[i-1]了,是[i]。不是看上層的,而是看本層的,這是完全背包和01背包的關鍵區別dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]];}}}return dp[n - 1][amount];}
}

思路:一維dp數組

  1. dp[i][j]含義不變
  2. 遞推公式:
    1. 本題 二維dp 遞推公式: dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]](正上方,左方)
    2. 壓縮成一維:dp[j] = dp[j] + dp[j - coins[i]]
  3. 初始化:dp[0] = 1
  4. 遍歷順序
    1. 在01背包的時候,遍歷j是要倒序遍歷的,因為dp[j]要依靠“正上方”和“左上方”的數據。但是完全背包,它依賴的是:“正上方”和“左方”的數據。
    2. “左方”的數據由何而來?得先遍歷才有,所以是for(j)是順序遍歷

附:01背包時候的二維公式和一維公式

二維: dp[i][j] = dp[i - 1][j] + dp[i - 1][j - coins[i]](正上方+左上方)

一維:dp[j] = dp[j] + dp[j - nums[i]];

因為要依賴左上方的數據,也就是上一層的舊數據,所以只能倒序遍歷。遍歷右的時候能取到左的數據

// 確定dp[i][j]含義,從0-i的coins中,任選一個或多個,裝滿容量為j的背包
class Solution {public int change(int amount, int[] coins) {// amount 是 bagSizeint n = coins.length;int[] dp = new int[amount + 1];// 初始化dp[0] = 1;// 動態規劃for (int i = 0; i < n; i++) {for (int j = coins[i]; j <= amount; j++) {dp[j] = dp[j] + dp[j - coins[i]];}}return dp[amount];}
}

377. 組合總和 Ⅳ

寫在前面:這個題目很有迷惑性,說是“組合”總和,但是這個“組合”又是可以有不同序列的——其實就是“排列”數,而不是求“組合”數。一定要弄清楚這個再繼續。

思路:一維dp數組

  1. dp[j]的定義:從[0-i](可重復)取任意個數,填滿背包j的組合(可排列!)有多少種?
  2. 確定遞歸公式:dp[j] = dp[j] + dp[j - nums[i]];(和上題一樣,不再詳細分析)
  3. 初始化:dp[0] = 1;
  4. 遍歷順序:先遍歷背包,再遍歷數字!!!先遍歷背包,再遍歷數字!!!先遍歷背包,再遍歷數字!!!
// 一維dp數組
// dp[j]的定義:從[0-i](可重復)取任意個數,填滿背包j的組合(可排列!)有多少種?
class Solution {public int combinationSum4(int[] nums, int target) {int n = nums.length;// bagSize 是 targetint[] dp = new int[target + 1];// 初始化dp[0] = 1;// 動態規劃for (int j = 0; j <= target; j++) {for (int i = 0; i < n; i++) {if (j >= nums[i]) {dp[j] = dp[j] + dp[j - nums[i]];}}// // 遍歷dp檢查// for(int k=0;k<=target;k++){//     System.out.print(dp[k]+" ");// }// System.out.println(" ");}return dp[target];}
}

為什么是“先遍歷背包,后遍歷數字”?

先說結論:

先遍歷數字,后遍歷背包——是組合數。

先遍歷背包,后遍歷數字——是排列數。

為什么會這樣呢?

公式 dp[j] += dp[j - nums[i]] 的核心邏輯是:

要計算 “填滿容量 j 的方式數”,可以先放入一個 nums [i],再累加 “填滿剩余容量 j-nums [i] 的方式數”

  • 當先遍歷數字時,“最后一個元素” 只能是當前數字(按固定順序),所以不會產生新順序。
  • 當先遍歷背包時,“最后一個元素” 可以是任何數字(在同一容量下嘗試所有數字),所以會產生不同順序的排列。

公式本身不關心順序,只關心 “是否加入當前數字”,而遍歷順序決定了 “加入數字的時機和范圍”,最終導致結果差異。

到這里,基本上講清楚了。可以再把518. 零錢兌換 II按照“先遍歷背包,后遍歷數字”的方式寫一遍,答案肯定錯誤。

57. 爬樓梯(卡碼網)

《代碼隨想錄》:

這其實是一個完全背包問題。

1階,2階,… m階就是物品,樓頂就是背包。

每一階可以重復使用,例如跳了1階,還可以繼續跳1階。

問跳到樓頂有幾種方法其實就是問裝滿背包有幾種方法。

思路:

  1. 確定dp含義:dp[i]:爬到有i個臺階的樓頂,有dp[i]種方法
  2. 確定遞推公式:dp[j] += dp[j - i];
  3. 初始化:dp[0] = 1;
  4. 完全背包問題:先背包,后數字(因為要先固定背包容量,再取數字,才有不同的順序)

要是能識別出來是完全背包問題,然后又剛好做完上一題的話,這道題其實可以直接復制過去AC。

import java.util.*;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();// bagSize 是 n// coins[] 是 m, [1,2,3...m]// dpint[] dp = new int[n + 1];// 初始化dp[0] = 1;// 先背包,后數字for (int j = 0; j <= n; j++) {for (int i = 1; i <= m; i++) {if (j >= i) {dp[j] += dp[j - i];}}}System.out.println(dp[n]);}
}

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

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

相關文章

Linux文件操作

Linux文件Linux下的文件類型b 塊設備文件---->存儲類設備&#xff08;硬盤&#xff09;c 字符設備文件--->輸入輸出設備d 目錄文件--->文件夾- 普通文件--> xxx.c xxx.h xxx.txt xxx.jpg xxx.mp4 a.outl 軟鏈接文件-->快捷方式s 套接字文件-->網絡通信p 管道…

Linux epoll 觸發模式詳解:LT vs ET

兩種核心觸發模式 1. 水平觸發 (Level-Triggered, LT) 工作方式: 當文件描述符處于就緒狀態時,epoll 會持續通知 只要狀態未改變,每次調用 epoll_wait 都會返回該描述符 特點: c // 內核處理邏輯 (ep_send_events_proc) if (!(epi->event.events & EPOLLET)) { /…

STM32學習筆記6-TIM-2輸出比較功能

第二部分&#xff0c;定時器的輸出比較功能OC&#xff08;Output Compare&#xff09;輸出比較輸出比較可以通過比較CNT與CCR寄存器值的關系&#xff0c;來對輸出電平進行置1、置0或翻轉的操作&#xff0c;用于輸出一定頻率和占空比的PWM波形每個高級定時器和通用定時器都擁有4…

MATLAB核心技巧:從入門到精通

一 1.數值 顯示 格式 format style 設置 eg: pi format longE; or 2.清除指令 clc 清除命令行窗口 clear 清除工作區 cls 3.搜索路徑設置 path(path,E:\ads\) or addpath 4.M文件 用戶把要實現的命令寫在一個以.m為擴展的文件中&#xff0c;然后由matlab系統進行解讀…

AnyDesk遠程工具免費版,v9.5.110綠色便攜版,秒連遠程桌面,剪貼板同步超實用

[軟件名稱]: AnyDesk遠程工具免費版 [軟件大小]: 7.5 MB [軟件大小]: 夸克網盤 | 百度網盤 軟件介紹 AnyDesk 讓遠程工作變得輕而易舉。無論您身處辦公室的另一端還是世界的另一側&#xff0c;只需在設備上下載、安裝并啟動 AnyDesk.exe&#xff0c;即可輕松訪問遠程屏幕。…

AI: 給Gemini CLI配上“說明書”, 精通的GEMINI.md項目記憶

嘿&#xff0c;各位技術同好&#xff01;今天我們來聊一個能極大提升AI編程助手效率的酷炫功能——Google Gemini CLI 中的 GEMINI.md 文件。 在日常開發中&#xff0c;我們越來越依賴像 Gemini 這樣的 AI 助手來幫我們寫代碼、調試 Bug 甚至重構項目。但大家是否遇到過這種情況…

[激光原理與應用-205]:光學器件 - LD與DFB的比較

一、相同點核心原理均基于半導體材料的受激輻射機制&#xff0c;通過電子-空穴復合產生光子。依賴諧振腔實現光反饋與放大&#xff0c;形成激光振蕩。采用電泵浦方式驅動&#xff0c;電流注入激發載流子&#xff0c;實現粒子數反轉。材料體系主要使用III-V族化合物半導體&#…

Cursor手機版:一半是神,一半是坑

大家好&#xff0c;我是羊仔&#xff0c;專注AI工具、智能體、編程。今天想和大家聊的這個工具&#xff0c;叫Cursor&#xff0c;可能很多朋友已經不陌生了&#xff0c;它作為一款AI原生代碼編輯器&#xff0c;之前可謂是風光無兩。但最近&#xff0c;它又搞了點新花樣&#xf…

康養休閑旅游服務虛擬仿真實訓室:筑牢技能人才培養的數字基石

隨著康養休閑旅游行業數字化、網絡化、智能化發展趨勢的深化&#xff0c;行業對高素質技能人才的實踐能力和數字素養提出了更高要求。康養休閑旅游服務虛擬仿真實訓室作為對接行業需求、創新實踐教學模式的重要載體&#xff0c;正成為中等職業教育康養休閑旅游服務專業人才培養…

【Python 高頻 API 速學 ⑤】

一、為什么把字典和集合放同一篇&#xff1f; ? 底層都是哈希表&#xff0c;API 設計高度對稱。 ? 日常任務無非「讀-寫-去重-集合運算」&#xff0c;這 5 個方法就能打穿。二、三件套 & 二板斧一覽名稱作用返回值原地&#xff1f;dict.get(key, default)安全讀取值或 de…

el-tree方法的整理

1.點擊樹的文字不要收縮僅點擊圖標的時候收縮 expand-on-click-node&#xff1a;是否在點擊節點的時候展開或者收縮節點&#xff0c; 默認值為 true&#xff0c;如果為 false&#xff0c;則只有點箭頭圖標的時候才會展開或者收縮節點。<el-tree:expand-on-click-node"f…

支持多網絡協議的測試工具(postman被無視版)

本文介紹接口調試工具&#xff0c;盡可能覆蓋支持多種網絡協議。寫給一直寫http接口&#xff0c;突然調試其他協議接口的開發 在后端開發中&#xff0c;接口調試工具的選擇取決于網絡協議類型和具體需求。以下是覆蓋多種協議的主流工具分類推薦&#xff0c;附關鍵特點和場景建議…

太陽平近點角詳解:概念、計算與應用

太陽平近點角詳解&#xff1a;概念、計算與應用 1. 基本定義 **太陽平近點角&#xff08;Mean Anomaly&#xff0c;M&#xff09;**是描述天體&#xff08;如地球&#xff09;在其軌道上平均運動位置的角度參數。對于太陽系中的行星或衛星而言&#xff0c;它表示假設天體以恒定…

ruoyi關閉shiro校驗,任何接口可以直接訪問

文章目錄1.找到ShiroConfig.java文件2.上述適用于get請求&#xff0c;post請求如何關閉&#xff1f;1.找到ShiroConfig.java文件 修改代碼 // 原始代碼 filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession,csrfValidateFilt…

數據結構進階 詳談紅黑樹

目錄 1. 紅?樹的概念 紅?樹的規則 紅?樹如何確保最?路徑不超過最短路徑的2倍的&#xff1f; 紅?樹的效率&#xff1a; 2. 紅?樹的實現 紅?樹的結構 紅?樹的插? 紅?樹樹插??個值的?概過程 情況1&#xff1a;變? 情況2&#xff1a;單旋變? 情況3&#…

【MySQL】MySQL去重查詢詳解

前言 在日常的數據庫操作中&#xff0c;數據去重是一個非常常見的需求。無論是查詢結果去重、數據清洗&#xff0c;還是統計分析&#xff0c;我們都需要掌握MySQL中的各種去重技術。本文將詳細介紹MySQL中常用的去重關鍵字和操作方法&#xff0c;結合實際業務場景&#xff0c;幫…

Pinterest視覺營銷自動化:亞矩陣云手機實例與多分辨率適配技術

Pinterest月活突破4.5億的視覺經濟時代&#xff0c;多分辨率適配與跨設備一致性成為品牌觸達用戶的核心挑戰。傳統營銷因素材模糊、設備參數固化&#xff08;如固定分辨率1080P&#xff09;、行為機械化&#xff08;如定時批量上傳&#xff09;&#xff0c;導致點擊率低于行業均…

01數據結構-圖的鄰接矩陣和遍歷

01數據結構-圖的鄰接矩陣和遍歷1.圖的遍歷1.1深度優先遍歷1.2廣度優先搜索2.鄰接矩陣的代碼實現1.圖的遍歷 1.1深度優先遍歷 深度優先搜索的過程類似于樹的先序遍歷&#xff0c;首先從例子中體會深度優先搜索&#xff0c;例如下圖1是個無向圖&#xff0c;采用深度優先算法遍歷…

OpenAI發布的GPT-5 更新了哪些內容,它的核心能力有哪些?AI編碼能力這么強,前端程序員何去何從?

目錄**1. GPT-5的核心能力與技術突破****1.1 智能水平的質變****1.2 代碼生成與優化****1.3 上下文處理與長文本能力****1.4 安全與可靠性改進****2. GPT-5的應用場景與案例****2.1 醫療領域****2.2 教育與學習****2.3 企業級應用****2.4 軟件開發****3. 技術細節與創新****3.1…

【無標題】AI 賦能日常效率:實用案例與操作心得分享

大語言模型&#xff08;LLM&#xff09;早已不再是實驗室里的專屬品&#xff0c;而是逐漸滲透到我們工作與生活的方方面面。從繁瑣的文檔處理到復雜的信息篩選&#xff0c;從學習輔助到日常規劃&#xff0c;AI 正以 "微生產力" 的形式重塑我們的效率邊界。本文將分享…