日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一和零!!

發布時間:2024/4/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一和零!! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


本題考察的不是多重背包

多重背包是每個物品,數量不同的情況。

本題中strs 數組里的元素就是物品,每個物品只有一個!

而m 和 n相當于是一個兩個維度的背包。

所以本題其實是01背包問題!

這不過這個背包有兩個維度,一個是m 一個是n,而不同長度的字符串就是不同大小的待裝物品。

開始動規五部曲:

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

dp[i][j]:最多有 i 個 0 和 j 個 1 的 strs 的最大子集的大小為 dp[ i ][ j ]。
或者可以理解為一個最多裝 i 個 0 和 j 個 1 的背包最多裝幾個這樣的物品。

確定遞推公式

dp[i][j] 可以由前一個strs里的字符串推導出來,strs里的字符串有zeroNum個0,oneNum個1。

dp[i][j] 就可以是 dp[i - zeroNum][j - oneNum] + 1。

然后我們在遍歷的過程中,取dp[i][j]的最大值。

所以遞推公式:dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);

回想一下01背包的遞推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

對比一下就會發現,字符串的zeroNum和oneNum相當于物品的重量(weight[i]),字符串本身的個數相當于物品的價值(value[i])。

這就是一個典型的01背包! 只不過物品的重量有了兩個維度而已。

dp數組如何初始化

01背包的dp數組初始化為0就可以。

因為物品價值不會是負數,初始為0,保證遞推的時候dp[i][j]不會被初始值覆蓋。

確定遍歷順序

外層for循環遍歷物品,內層for循環遍歷背包容量且從后向前遍歷!

那么本題也是,物品就是strs里的字符串,背包容量就是題目描述中的m和n。

for (string str : strs) { // 遍歷物品int oneNum = 0, zeroNum = 0;for (char c : str) {if (c == '0') zeroNum++;else oneNum++;}for (int i = m; i >= zeroNum; i--) { // 遍歷背包容量且從后向前遍歷!for (int j = n; j >= oneNum; j--) {dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);}} }

舉例推導dp數組

以輸入:[“10”,“0001”,“111001”,“1”,“0”],m = 3,n = 3為例

最后dp數組的狀態如下所示:

class Solution { public:int findMaxForm(vector<string>& strs, int m, int n) {vector<vector<int>> dp(m+1,vector<int>(n+1,0));for(auto ch : strs){int zeroNum=0,oneNum=0;for(int ii=0;ii<ch.size();ii++){if(ch[ii]=='0') zeroNum++;else oneNum++;}for(int ii=m;ii>=zeroNum;ii--){for(int jj=n;jj>=oneNum;jj--)dp[ii][jj]=max(dp[ii][jj],dp[ii-zeroNum][jj-oneNum]+1);}}return dp[m][n];} };

可以理解為一個物品有兩種重量不同的物質組成,一個是物質1,一個是物質2。而放物品的包也有兩個不同的兜用來分別裝某物品的物質1和物質2

總結

以上是生活随笔為你收集整理的一和零!!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。