《dp補卡——01背包問題》

在這里插入圖片描述

目錄

  • 01背包
        • [416. 分割等和子集](https://leetcode-cn.com/problems/partition-equal-subset-sum/)
        • [1049. 最后一塊石頭的重量 II](https://leetcode-cn.com/problems/last-stone-weight-ii/)
        • [494. 目標和](https://leetcode-cn.com/problems/target-sum/)

01背包

1、dp數組以及下標含義

dp[i][j]標識從下標為[0,1]的物品里任意取,放進容量為j的背包,價值總和最大是多少?

在這里插入圖片描述

2、確定遞推公式

dp[i][j]可以由兩個方向推出:

1、dp[i-1][j],背包容量為j,里面不放入物品i的最大價值,此時dp[i][j] = dp[i-1][j]

2、dp[i-1][i-weight[i]]推出,背包容量為i-weight[i]的時候此時dp[i][j] = dp[i-1][j-weight[i]]+valuep[i];

所以遞推公式為:

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

3、dp數組如何初始化

關于初始化,一定要和dp數組的定義吻合。

如果背包容量j為0的話,dp[i][0]無論是選取哪些物品,背包價值總和一定為0。

由遞推可知i是由i-1推出來的,那么i為0時一定要初始化。

dp[0][j]存放編號為0的物品時,各個容量的背包能存放的最大價值:

for(int j = bagWeight; j >= weight[0]; j--)
{dp[0][j] = dp[0][j-weight[0]] + value[0];
}

這里需要注意,初始化是倒序遍歷。

dp[0][j]表示容量為j的背包存放物品0時候的最大價值。由于每個物品只有1個,如果dp[0][j]必須為初值,正序遍歷,物品0會被重復加入多次。

dp[i][j]在推導的時候一定是取價值最大的數,如果題目給的價值都是正整數,那么下標初始化為0.如果價值里面有負數,初始化為負無窮。只要保證dp數組在遞推公式的過程中取最大的價值,而不是被初始值覆蓋。

所以dp數組初始化如下:

vector<vector<int>> dp(weight.size() + 1,vector<int>(bagWeight + 1,0));
for(int j = bagWeight; j >= weight[0]; j--)
{dp[0][j] = dp[0][j-weight[0]] + value[0];
}

4、確定遍歷順序

有兩個遍歷維度:物品與背包重量,先遍歷物品更好理解。

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]]+values[i])}
}

滾動數組優化

1、確定dp數組的定義

dp[j]:容量為j的背包,所背的物品價值可以最大為dp[j]。

2、一維dp遞推公式

dp[j]可以通過dp[j-weight[i]]推導,其表示容量為j-weight[i]的背包所背的最大價值。

dp[j-weight[i]]+value[i]表示容量為j-物品i重量的背包加上物品i的價值。(即容量為j的背包放入物品i之后的價值)此時dp[j]有兩個選擇,一個是取自己dp[j],一個是取dp[j-weight[i]]+value[i].

所以遞推公式為:

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

3、初始化

假設物品價值都是大于0的,dp數組初始化的時候都初始化為0

4、確定遍歷順序

for(int i = 0; i < weight.size(); i++)	//遍歷物品
{for(int j = bagWeight; j >= weight[i]; j--)	//遍歷背包容量{dp[j] = max(dp[j],dp[j-weight[i]]+value[i]);}
}

二維遍歷時,背包容量從小到大,一維遍歷,背包容量從大到小。

這是因為倒序遍歷是為了保證物品i只被放入一次。二維dp,dp[i][j]是通過上一層dp[i-1][j]計算得到的,所以本層的dp[i][j]并不會產生覆蓋。

一維01背包測試代碼:

void test_one_dim_01bag()
{vector<int> weight = {1,3,4};vector<int> value = {15,20,30};int bagWeight = 4;//初始化vector<int> dp(bagWeight+1,0);for(int i = 0; i < weight[i]; i++)	//遍歷物品{for(int j = bagWeight; j >= weight[i]; j--)	//遍歷背包容量{dp[j] = max(dp[j],dp[j-weight[i]] + value[i]);}}cout << dp[bagWeight] << endl;
}

416. 分割等和子集

求集合里是否出現總和為sum/2的子集。

背包體積為sum/2

背包放入的商品的重量為元素的數值,價值也為元素的數值

背包如何正好被裝滿,說明找到了總和為sum/2的子集

背包中每個元素都是不可重復放入的。

1、確定dp數組以及下標含義

dp[j]表示容量為j的背包,所背物品價值可以最大為dp[j]。

dp[j]表示背包總容量為j,最大可以湊成j的子集總和為dp[j]。

2、確定遞推公式

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

3、初始化

vector<int> dp(target+1,0);	//target為背包容量

4、確定遍歷順序

for(int i = 0; i < nums.size(); i++)
{for(int j = target; j >= nums[i]; j--){dp[j] = max(dp[j],dp[j-nums[i]]+nums[i]);}
}

AC代碼:

class Solution {
public:bool canPartition(vector<int>& nums) {int sum = 0;for(int num : nums){sum += num;}if(sum % 2 != 0) return false;int target = sum / 2;vector<int> dp(target+1,0);for(int i = 0; i < nums.size(); i++){for(int j = target; j >= nums[i]; j--){dp[j] = max(dp[j],dp[j-nums[i]]+nums[i]);if(dp[j] == target) return true;}}if(dp[target] == target) return true;else return false;}
};

1049. 最后一塊石頭的重量 II

將石頭盡量分成兩堆相同重量,然后相撞。分成兩堆的思路與上一題一致。

class Solution {
public:int lastStoneWeightII(vector<int>& stones) {int sum = 0;for(int stone : stones){sum += stone;}int target = sum / 2;//dp[target],容量為target的背包最多能背多重的石頭vector<int> dp(target+1,0);for(int i = 0; i < stones.size(); i++){for(int j = target; j >= stones[i]; j--){dp[j] = max(dp[j],dp[j-stones[i]] + stones[i]);}}return sum - dp[target]*2;}
};

494. 目標和

所有數字可以分為兩堆,一堆符號為正,一堆符號為負。
pos + neg = S 且 pos - neg = sum
所以pos = (S+sum)/2,問題轉化為集合nums中找出和為pos的組合。
此時問題就轉化為,裝滿容量為pos背包,有幾種方法。
這次和之前遇到的背包問題不一樣了,之前都是求容量為j的背包,最多能裝多少。
本題則是裝滿有幾種方法。其實這就是一個組合問題了。
1、確定dp數組以及下標
dp[j]表示,填滿體積為j的背包,有dp[j]種方法。

2、確定遞推公式
不考慮nums[i],填滿容量為j-nums[i]的背包,有dp[j-nums[i]]種方法,
如果能搞到nums[i],則填滿容量為j-nums[i]的背包,就有dp[j]+dp[j-nums[i]]種方法。

dp[j] += dp[j-nums[i]]

3、初始化dp數組
dp[0] = 1,裝滿容量為0的背包,有1種方法。其他dp[i]均設置為0,在不知道nums[i]的情況下,沒有方法。

4、確定遍歷順序
nums外循環,j內循環倒序。

AC代碼:

class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {int sum = 0;for(int num : nums)sum += num;//如果絕對值和比targetabs小,說明都用同一個符號也不能湊成if(sum < abs(target)) return 0;//如果不能完整的分成兩組,那么說明沒有方法if((target + sum) % 2 == 1) return 0;int bagWeight = (target + sum)/2;vector<int> dp(bagWeight+1,0);dp[0] = 1;for(int i = 0; i < nums.size(); i++){for(int j = bagWeight; j >= nums[i]; j--){dp[j] += dp[j-nums[i]];}}return dp[bagWeight];}
};

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

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

相關文章

用JavaScript往DIV動態添加內容

參考&#xff1a;http://zhidao.baidu.com/link?url6jSchyqPiEYCBoKdOmv52YHz9r7MTBms2pK1N6ptOX1kaR2eg320mlW1Sr6n36hpOeOadBxC2rWWGuhZPbms-K <div id"show"></div>要填充的數據為: 這是一個測試例子.jquery&#xff1a;$(function(){ var data …

《dp補卡——完全背包問題》

N件物品和一個最多能背重量為W的背包。第i件物品的重量為weight[i]&#xff0c;得到的價值是value[i]。每件物品都有無限個(可以放入背包多次)&#xff0c;求解將哪些物品裝入背包里物品價值總和最大。 01背包和完全背包唯一不同在于遍歷順序上。 01背包的核心代碼&#xff1a…

Java中的類型轉換

類型轉換 (Typecasting) Typecasting is a term which is introduced in all the language similar to java. Typecasting是一個用與Java類似的所有語言引入的術語。 When we assign primitive datatype to another datatype. 當我們將原始數據類型分配給另一個數據類型時。 I…

讓crash文件中的內存地址變成函數名稱,

假如程序員編譯了inhouse給測試。 如果在測試過程中出現奔潰現象&#xff0c;我想程序員一般會來看Device Log 也就是 crash文件 如果crash文件遇到如下的情況&#xff0c;在重要的地方看不到函數名稱。我想是一件很奔潰的事情。 1 Exception Type: EXC_BAD_ACCESS (SIGSEGV)2…

《dp補卡——多重背包》

多重背包簡介&#xff1a; 有N種物品和一個容量為V的背包。第i種物品最多有Mi件可用&#xff0c;每件耗費的空間為Ci&#xff0c;價值為Wi。求解將哪些物品裝入背包可使得這些物品耗費的空間總和不超過背包容量&#xff0c;且價值總和最大。 將Mi件攤開&#xff0c;就是一個01背…

kafka消息確認ack_什么是確認(ACK)? ACK代表什么?

kafka消息確認ackACK&#xff1a;致謝 (ACK: Acknowledgment) An acknowledgment (ACK) is a signal that is passed among the communicating processes, computers, or devices to indicate acknowledgment, or delivery of the message, as a component of a communications…

CocoaAsyncSocket 套接字

CocoaAsyncSocket 套接字 https://github.com/robbiehanson/CocoaAsyncSocket Asynchronous socket networking library for Mac and iOS 用于iOS以及Mac的異步套接字網絡庫。 TCP GCDAsyncSocket and AsyncSocket are TCP/IP socket networking libraries. Here are the key…

谷歌瀏覽器設置緩存方法

谷歌瀏覽器設置緩存方法&#xff1a; 1、在桌面Google Chrome快捷方式&#xff0c;目標&#xff1a;找到 C:\Users\Splendid\AppData\Local\…\Application\chrome.exe 在這后面加上-Disk-Cache-Dir”Z:\TEMP” 注意: -Disk前面有空格&#xff0c;”Z:\TEMP” 是文件存放在Z盤T…

《dp補卡——買賣股票問題》

目錄121. 買賣股票的最佳時機貪心dp思路滾動數組優化122. 買賣股票的最佳時機 II123. 買賣股票的最佳時機 III188. 買賣股票的最佳時機 IV309. 最佳買賣股票時機含冷凍期714. 買賣股票的最佳時機含手續費121. 買賣股票的最佳時機 貪心 取最左最小值&#xff0c;取最右最大值&…

oo0ooo0ooo0oo_OoO的完整形式是什么?

oo0ooo0ooo0ooOoO&#xff1a;外出 (OoO: Out of Office) OoO is an abbreviation of "Out of Office". OoO是“不在辦公室”的縮寫。 It is an expression, which is commonly used in the Gmail platform. It is written in the body or the subject of the email…

SP2010開發和VS2010專家食譜--第三章節--高級工作流(2)--為沙盒解決方案創建自定義活動...

盡管沙河解決方案功能有限&#xff0c;你仍然可以開發自定義活動&#xff0c;在SharePoint Designer中使用而不用改變web.config或添加.ACTION文件到根文件夾。 轉載于:https://www.cnblogs.com/crazygolf/p/3856795.html

sql where 1=1和 0=1 的作用

where 11; 這個條件始終為True&#xff0c;在不定數量查詢條件情況下&#xff0c;11可以很方便的規范語句。 一、不用where 11 在多條件查詢中的困擾 舉個例子&#xff0c;如果您做查詢頁面&#xff0c;并且&#xff0c;可查詢的選項有多個&#xff0c;同時&#xff0c;還讓用戶…

j@2ff4f00f_J4F的完整形式是什么?

j2ff4f00fJ4F&#xff1a;只是為了好玩 (J4F: Just For Fun) J4F is an abbreviation of "Just For Fun". J4F是“ Just For Fun”的縮寫 。 It is an expression, which is commonly used in messaging or chatting on social media networking sites like Faceboo…

《dp補卡——子序列問題》

目錄300. 最長遞增子序列674. 最長連續遞增序列718. 最長重復子數組1143. 最長公共子序列53. 最大子序和392. 判斷子序列115. 不同的子序列583. 兩個字符串的刪除操作72. 編輯距離647. 回文子串 &#xff08;與 5.最長回文子串思路差不多&#xff09;516. 最長回文子序列300. 最…

[LeetCode] Maximal Rectangle

Given a 2D binary matrix filled with 0s and 1s, find the largest rectangle containing all ones and return its area. 在做 Largest Rectangle in Histogram的時候有人說可以用在這題&#xff0c;看了一下還真是&#xff0c;以每行為x軸&#xff0c;每列往上累計的連續的…

什么是alpha測試_什么是ALPHA?

什么是alpha測試Α (ALPHA) Alpha is the first and foremost letter of the Greek alphabet. In the classification of Greek numerals or numbers, it constitutes a value of 1. Alpha是希臘字母的第一個也是最重要的字母 。 在希臘數字或希臘數字的分類中&#xff0c;它的…

《leetcode : 647. 回文子串 思考分析雙指針解法》

647. 回文子串 如何確定是回文串&#xff1a; 找中心然后往兩邊擴散&#xff0c;判斷是否對稱即可。 在遍歷中心點的時候&#xff0c;注意中心點可以是一個元素也可以是兩個元素。 class Solution { public:int cal_two_extend(const string& s,int i,int j,int n){int re…

天草初級班(3)

算術運算指令算術運算指令是反映CPU計算能力的一組指令&#xff0c;也是編程時經常使用的一組指令。它包括&#xff1a;加、減、乘、除及其相關的輔助指令。 該組指令的操作數可以是8位、16位和32位(80386)。當存儲單元是該類指令的操作數時&#xff0c;該操作數的尋址方式可以…

4.3.3版本之引擎bug

bug描述&#xff1a;   IOS設備上&#xff0c;當使用WWW www WWW.LoadFromCacheOrDownload(url, verNum); 下載資源時&#xff0c;第一次下載某個資源&#xff0c;www.assetBundle必定為空。 解決辦法&#xff1a;   引擎版本降到4.3.2或者升到4.3.4或更高。 這個bug絕對是…

sml完整形式_411的完整形式是什么?

sml完整形式411&#xff1a;信息 (411: Information) 411 is an abbreviation of “Information". 411是“信息”的縮寫 。 It is an expression, which is commonly used in messaging or chatting on social media networking sites like Facebook, Yahoo Messenger, a…