動態規劃——完全背包問題(公式推導,組合、排列)

????????本文章是對于完全背包 一些題型(如題目所示,組合、排列和最小值類型)的總結和理解,依次記錄一下,方便回顧與復習。

? ? ? ? 本文章是基于個人所總結 實現的,但在其中遇到了一些疑惑與困難,所以總結一篇與完全背包相關的問題。

? ? ? ? 題型分為 完全背包 求組合問題 、 求排列問題、 求最小值問題.

但這一切都是基于完全背包,我們先來介紹一下什么是完全背包。

目錄

完全背包問題

二維dp

?二維優化

一維dp(滾動數組)

完全背包組合和排列問題


完全背包問題

????????有N件物品和一個最多能背重量為W的背包。第i件物品的重量是weight[i],其價值為value[i] 。每件物品都有無限個(也就是可以放入背包多次),求解將哪些物品裝入背包里物品價值總和最大。(即如何在有限的空間中 盡可能放到整體價值最高).

????????完全背包和01背包問題唯一不同的地方就是,完全背包每種物品有無限件;而01背包每個物品只有一件。

? ? ? ? 在這里我認為對你對01背包 已經有一定的了解,便不再深入贅述。如果不了解01背包,最好先了解之后再繼續閱讀。

二維dp

這是 01背包的核心代碼

     // 二維數組vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));// 初始化for (int j = weight[0]; j <= bagweight; j++) {dp[0][j] = value[0];}// weight數組的大小 就是物品個數for(int i = 1; i < weight.size(); i++) { // 遍歷物品for(int j = 0; j <= bagweight; j++) { // 遍歷背包容量if (j < weight[i]) dp[i][j] = dp[i - 1][j];//如果當前背包容量小于物品體積,則直接不做選擇else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);//如果大于物品體積,則取 選擇當前物品 和 不選擇當前物品 的最大值}}

01背包是每次從中選取一個物品 一次,即如果作選取決策的話,當前重量j 只用減去一個weight[i],所以選取后的重量是dp[i-1][j-weight[i]].

注意我下面所說的當前容量,而沒有說背包總容量。因為我們是從小到大遍歷的背包容量。

完全背包是 可以選取一個物品 多次(k>=0),即如果作選取決策的話當前重量j 要減去 k個weight[i],具體多少取決于當前背包容量的大小。所以我們for循環 k從0開始遍歷,直至 大于當前背包容量停止。而我們也要做出抉擇,即選出0-k次中最大的值,如下:

max (dp[i-1][j-weight[i] * k] + value[i]*k)

如果作不選取 決策的話,那么當前的值就不變化,繼承上一次的值。即dp[i][j] = dp[i-1][j];

?所以現在狀態轉移方程為:

dp[i][j] = max {?max (dp[i-1][j-weight[i] * k] + value[i]*k), dp[i-1][j] }. 其中(1 <= k <= j/weight[i]

代碼如下:

    //n代表物品的數量,v代表背包的容量,weight[i]代表第i個物品的體積,value[i]是第i個物品的價值vector<vector<int>> dp(N+1,vector<int>(N+1,0));//遍歷背包物品for(int i = 1; i <= n; i++){  //遍歷背包容量for(int j = 1; j <= v; j++){//每次選取k件 物品i ,如果容量大于 當前容量j,則停止for(int k = 1; k * weight[i] <= j; k++){//這句代碼相當于max (dp[i-1][j-weight[i] * k] + value[i]*k),而由于k每次在同一行,所以每次和dp[i][j]進行比較。當然這里寫max(dp[i-1],...)也沒關系,因為最后都是取的 dp[i-1][j-k*weight[i]]+value[i]*k)的最大值。選dp[i-1][j]相當于每次都和第一次比較,而選dp[i][j]相當于每次都和上一次的進行比較,所以dp[i][j]最后一定是最大值dp[i][j] = max(dp[i][j],dp[i-1][j-k*weight[i]]+value[i]*k);}//dp[i][j] = max(dp[i-1][j],dp[i][j]); //這句代碼其實不用加,因為上面第一次k一定等于0,//所以相當于第一次已經比較了。這里寫只是為了更好的顯示上面的思路}}return dp[n-1][v];

?二維優化

上面我們用了三重for循環,時間復雜度太高了,我們有沒有辦法把它轉化成二維的呢?

記得上面剛說的這個狀態轉移方程:

一.dp[i][j] = max {?max (dp[i-1][j-weight[i] * k] + value[i]*k), dp[i-1][j] }.

其中(1 <= k <= j/weight[i])

我們看到k的取值最小值為1,那我們不妨先把這 一個物品放進去

得到:

二.dp[i][j] = max {max(dp[i-1][j-weight[i]*k -weight[i]]+value[i]*k +value[i]),dp[i-1][j]);

此時k的取值范圍為:(0?<= k <= j/weight[i]-1)

對于式子一,我們完全可以可以把式子簡化為如下:

三.dp[i][j] = max(dp[i-1][j-weight[i] * k] + value[i]*k),其中

其中(0?<= k <= j/weight[i])

這是如何做到的呢?我們發現式子一 k的最小值是1,那么當我們讓k=0時,發現dp[i-1][j-weight[i] * k] + value[i]*k)就是dp[i-1][j].所以我們完全可以合并這兩個!最后只留下一個max,只不過k的最小值由1變成了0.

j=j-weight[i]時,我們將其帶入到式子三:

四.dp[i][j-weight[i]] = max(dp[i-1][j-weight[i] - weight[i]*k] + value[i]*k);其中:

(0?<= k <= j/weight[i]-1)

此時我們再用式子二對比式子四:

二.dp[i][j] = max {max(dp[i-1][j-weight[i]*k -weight[i]]+value[i]*k +value[i]),dp[i-1][j]);

四.dp[i][j-weight[i]] = max(dp[i-1][j- weight[i]*k -weight[i]] + value[i]*k);

?可以發現它們是畫圈的這一部分完全等價的!范圍也是一樣的。我們我們把式子四 替換到式子二中:

dp[i][j] = max(dp[i][j-weight[i]]+value[i],dp[i-1][j]).

這就是我們最終推導出的公式!!!

所以我們再也不需要寫那三重循環了,直接二維循環就可以,如下:

    vector<vector<int>> dp(N+1,vector<int>(N+1,0));//遍歷背包物品for(int i = 1; i <= n; i++){  //遍歷背包容量for(int j = 0; j <= v; j++){//如果選擇的話if(j >= weight[i])dp[i][j] = max(dp[i][j-weight[i]]+value[i],dp[i-1][j]);//如果不選擇elsedp[i][j] = dp[i-1][j];}}

一維dp(滾動數組)

和01背包問題問題類似,我們同樣可以轉化為把? 二維數組轉化為一維數組,因為它們都只依賴于上一行的狀態。

因此我們由

dp[i][j] = max(dp[i][j-weight[i]]+value[i],dp[i-1][j]);

可以轉化為一維dp數組:

dp[j] = max(dp[j-weight[i]]+value[i],dp[j]);

修改完畢后,代碼如下:

    vector<int> dp(N+1,0);for(int i = 1; i <= n; i++){for(int j = weight[i]; j <= v; j++){dp[j] = max(dp[j-weight[i]]+value[i],dp[j]);}}return dp[v];

完全背包組合和排列問題

先說結論:

利用背包 求組合數外層遍歷物品,內層遍歷 物品容量

利用背包求 排列數?是 想外層遍歷物品的容量內層再遍歷 物品.

組合 不強調順序,而排列強調順序

為什么是這樣呢?

假設你有價值為1元 和 2元的硬幣,數量分別有無限個,那么讓你湊成價值為5元的方案有多少種?

這個里面,有這樣的兩種方案:1 2 2? ? 2? 1 2??

如果是組合數,它們將會被視為一種組合,而如果是排列數,那么它們將是兩種不同的排列

具體來說:

假設你先遍歷的物品數量,那么你后面只能按照固定的順序遍歷了。

假設物品有 abc,那么你也只能按照abc這個順序來放入了. b根本沒機會放到a的前面,因為遍歷完a結束 才遍歷b的. 所以這樣是求組合數

相反的,假設你先遍歷的物品容量,再遍歷物品數量,這樣每個物品都有機會放入背包中,順序也不固定,假設裝a不合適,我可以裝b(ee,真沒別的意思),隨著遍歷背包容量變大,說不定原來的a又適合裝入了,這樣就有了不同的順序了。

大家可以在leetcode上做下面的例題感受:

求組合數:
518.零錢兌換II

求排列數:

377.組合總和IV

到這里,關于完全背包的一些基礎相關的問題就講完了,實際上還需要大家看視頻或者做更多題感受到,可以看看題解中一些人發表的,他們發表的一種種類型及對應的題目可以非常好的鞏固自己!

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

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

相關文章

Spring基于注解開發

Component的使用 基本Bean注解&#xff0c;主要是使用注解的方式替代原有的xml的<bean>標簽及其標簽屬性的配置&#xff0c;使用Component注解替代<bean>標簽中的id以及class屬性&#xff0c;而對于是否延遲加載或是Bean的作用域&#xff0c;則是其他注解 xml配置…

IntelliJ IDEA 的 HTTP 客戶端的高級用法

本心、輸入輸出、結果 文章目錄 IntelliJ IDEA 的 HTTP 客戶端的高級用法前言HTTP 請求對 gRPC 請求的支持對 GraphQL 和 WebSocket 請求的支持環境文件OpenAPI 補全用于持續集成的 HTTP 客戶端 CLI花有重開日,人無再少年實踐是檢驗真理的唯一標準IntelliJ IDEA 的 HTTP 客戶端…

keepalived 高可用主備

實驗采用兩臺centos9 nginxkeepalived 一共兩臺&#xff0c;進行主備切換 主服務器 192.168.100.105 備用 192.168.100.106 虛擬ip 192.168.100.200 安裝 dnf install vim wget curl vim net-tools nginx keepalivedUndefined nginx 配置需要更改為虛擬ip server {listen …

四招打造完美分層自動化測試框架,讓測試更高效!

寫在前面 我們剛開始做自動化測試&#xff0c;可能寫的代碼都是基于原生寫的代碼&#xff0c;看起來特別不美觀&#xff0c;而且感覺特別生硬。 來看下面一段代碼&#xff1a; 具體表現如下&#xff1a; driver對象在測試類中顯示 定位元素的value值在測試類中顯示 定位元素…

Navicat 技術指引 | 適用于 GaussDB 分布式的用戶/權限功能

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式數據庫。GaussDB 分布式模式更適合對系統可用性和數據處理能力要求較高的場景。Navicat 工具不僅提供可視化數據查看和編輯功能&#xff0c;還提供強大的高階功能&#xff08;如模型、結…

干貨:軟文推廣中的關鍵詞類別有哪些?

軟文推廣如果想要增加文案曝光率&#xff0c;seo是其主要的傳播方式之一&#xff0c;因而好的關鍵詞十分重要&#xff0c;這里的關鍵詞指得是針對搜索引擎而言&#xff0c;由用戶輸入搜索引擎框中的提示性文字&#xff0c;只要關鍵詞設置得好&#xff0c;軟文就能通過搜索引擎精…

因為 postman環境變量全局變量設置好兄弟被公司優化了!

postman環境變量、全局變量設置 在公司中&#xff0c;一般會存在開發環境、測試環境、線上環境等&#xff0c;如果需要在不 同的環境下切換做接口測試&#xff0c;顯然我們需要把所有接口的域名進行修改&#xff0c;如果接 口測試用例較多&#xff0c;那么修改會非常費力&…

springboot(ssm大學生志愿者管理系統 志愿者管理平臺 Java系統

springboot(ssm大學生志愿者管理系統 志愿者管理平臺 Java系統 開發語言&#xff1a;Java 框架&#xff1a;ssm/springboot vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服務器&#xff1a;tomcat 數據庫&#xff1a;mysql 5.7&#xff08;或8.0&#xff…

Python與ArcGIS系列(十五)根據距離抓取字段

目錄 0 簡述1 實例需求2 arcpy開發腳本0 簡述 在處理gis數據的時候,會遇到這種需求:將一個圖層與另一個圖層中相近的要素進行字段賦值。本篇將介紹如何利用arcpy及arcgis的工具箱實現這個功能。 1 實例需求 為了介紹這個功能的實現,我們需要有一個特定的功能需求。在這里選…

視頻號小店怎么選品?選品技巧及思維,教程如下!

我是電商珠珠 開通視頻號小店后&#xff0c;除了定類目之外&#xff0c;最終的就是選品了。 很多人不知道怎么選品&#xff0c;特別是新手小白&#xff0c;做起來比較難一些。店鋪也會很少有流量進入&#xff0c;沒有流量曝光的話&#xff0c;店鋪的銷量就更不用提了。 我做…

L1-019:誰先倒

題目描述 劃拳是古老中國酒文化的一個有趣的組成部分。酒桌上兩人劃拳的方法為&#xff1a;每人口中喊出一個數字&#xff0c;同時用手比劃出一個數字。如果誰比劃出的數字正好等于兩人喊出的數字之和&#xff0c;誰就輸了&#xff0c;輸家罰一杯酒。兩人同贏或兩人同輸則繼續下…

【Android】Java NIO(New I/O)的`Selector`類來實現非阻塞的Socket監聽

如果你不想使用循環來監聽客戶端的連接和數據&#xff0c;你可以使用Java NIO&#xff08;New I/O&#xff09;的Selector類來實現非阻塞的Socket監聽。Selector類提供了一種選擇一組已經就緒的通道的機制&#xff0c;這樣你就不需要使用循環來等待連接和數據。 以下是使用Sel…

Axure網頁端高復用組件庫, 下拉菜單文件上傳穿梭框日期城市選擇器

作品說明 組件數量&#xff1a;共 11 套 兼容軟件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 應用領域&#xff1a;web端原型設計、桌面端原型設計 作品特色 本作品為「web端組件庫」&#xff0c;高保真高交互 (帶仿真功能效果)&#xff1b;運用了動態面板、中繼…

使用pytorch查看中間層特征矩陣以及卷積核參數

這篇是我對嗶哩嗶哩up主 霹靂吧啦Wz 的視頻的文字版學習筆記 感謝他對知識的分享 1和4是之前講過的alexnet和resnet模型 2是分析中間層特征矩陣的腳本 3是查看卷積核參數的腳本 1設置預處理方法 和圖像訓練的時候用的預處理方法保持一致 2實例化模型 3載入之前的模型參數 4載入…

小白理解GPT的“微調“(fine-tuning)

對于GPT-3.5&#xff0c;我們實際上并不能在OpenAI的服務器上直接訓練它。OpenAI的模型通常是預訓練好的&#xff0c;也就是說&#xff0c;它們已經在大量的語料上進行過訓練&#xff0c;學習到了語言的基本規則和模式。 然而&#xff0c;OpenAI提供了一種叫做"微調"…

Pandas操作數據庫

一&#xff1a;Pandas讀取數據庫數據 二&#xff1a;Pandas讀取海量數據 三&#xff1a;Pandas向數據庫存數據 四&#xff1a;Pandas寫入海量數據

理想中的PC端剪切板工具,應該有哪些功能?

在日常工作中&#xff0c;我們經常需要復制和粘貼文本、圖片和鏈接。 首先&#xff0c;這款剪切板功能應該在不使用時不顯示窗口&#xff0c;以避免干擾我們的工作。它應該在后臺靜默記錄剪切板歷史&#xff0c;以便我們可以隨時查看之前的記錄。 其次&#xff0c;當我們需要…

A類中創建posix線程,線程間如何通信

如果你在類A中使用pthread_create創建了線程B&#xff0c;而線程B需要與類A進行通信&#xff0c;你可以考慮以下兩種方法&#xff1a; 使用回調函數&#xff1a; 在創建線程B時&#xff0c;通過參數傳遞一個回調函數&#xff0c;該回調函數可以在線程B中執行&#xff0c;并在完…

上海寶山區12月8日發生一起火災 火勢已撲滅 揭秘AI如何“救援”

在這個冬日的早晨&#xff0c;上海寶山區的居民經歷了一場驚心動魄的火災。幸運的是&#xff0c;火勢很快就被撲滅了。但這起事件不禁讓我們思考&#xff1a;如何更有效地預防和應對這樣的緊急情況&#xff1f; 這時候&#xff0c;就不得不提到北京富維圖像公司的一項創新技術—…

我的隱私計算學習——國密SM2和國密SM4算法

此篇是我筆記目錄里的安全保護技術&#xff08;七&#xff09;&#xff0c;前篇可見&#xff1a; 隱私計算安全保護技術&#xff08;一&#xff09;&#xff1a;我的隱私計算學習——混淆電路-CSDN博客 隱私計算安全保護技術&#xff08;二&#xff09;&#xff1a;我的隱私計…