給你乙個二進位制字串陣列 strs 和兩個整數 m 和 n 。
請你找出並返回 strs 的最大子集的大小,該子集中 最多 有 m 個 0 和 n 個 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。
示例 1:
輸入:strs = [「10」, 「0001」, 「111001」, 「1」, 「0」], m = 5, n = 3
輸出:4
解釋:最多有 5 個 0 和 3 個 1 的最大子集是 ,因此答案是 4 。
其他滿足題意但較小的子集包括 和 。 不滿足題意,因為它含 4 個 1 ,大於 n 的值 3 。
示例 2:
輸入:strs = [「10」, 「0」, 「1」], m = 1, n = 1
輸出:2
解釋:最大的子集是 ,所以答案是 2 。
狀態有三個, [揹包對1的容量]、[揹包對0的容量]和 [可選擇的字串];選擇就是把字串[裝進揹包]或者[不裝進揹包]。
明白了狀態和選擇,只要往這個框架套就完事兒了:
for 狀態1 in 狀態1的所有取值:
for 狀態2 in 狀態2的所有取值:
for …
dp[狀態1][狀態2][…] = 計算(選擇1,選擇2…)
- 第二步,要明確dp陣列的定義:
首先,[狀態]有三個,所以需要乙個三維的dp陣列。
dp[i][j][k]的定義如下:
若只使用前i個物品,當揹包容量為j個0,k個1時,能夠容納的最多字串數。
經過以上的定義,可以得到:
base case為dp[0][…][…] = 0, dp[…][0][0] = 0。因為如果不使用任何乙個字串,則揹包能裝的字串數就為0;如果揹包對0,1的容量都為0,它能裝的字串數也為0。
我們最終想得到的答案就是dp[n][zeronums][onenums],其中n為字串的的數量。
第三步,根據選擇,思考狀態轉移的邏輯:
注意,這是乙個0-1揹包問題,每個字串只有乙個選擇機會,要麼選擇裝,要麼選擇不裝。
如果你不能把這第 i 個物品裝入揹包(等同於容量不足,裝不下去),也就是說你不使用strs[i]這乙個字串,那麼當前的字串數dp[i][j][k]應該等於dp[i - 1][j][k],繼承之前的結果。
如果你可以把這第 i 個物品裝入了揹包(此時揹包容量是充足的,因此要選擇裝或者不裝),也就是說你能使用 strs[i] 這個字串,那麼 dp[i][j] 應該等於 max(dp[i - 1][j][k], dp[i - 1][j - cnt[0]][k - cnt[1]] + 1)。 max函式裡的兩個式子,分別是裝和不裝strs[i的字串數量。(cnt 是根據strs[i]計算出來的。)
比如說,如果你想把乙個cnt = [1,2]的字串裝進揹包(在容量足夠的前提下),只需要找到容量為
[j - 1][k - 2]時候的字串數再加上1,就可以得到裝入後的字串數了。
由於我們求的是最大值,所以我們要求的是裝和不裝中能容納的字串總數更大的那乙個。
int
findmaxform
(vector
& strs,
int m,
int n)
for(
int j=
0;j1;j++)}
}return dp[num]
[m][n]
;}
ps:遍歷字串
使用 for (char c : s)時會複製乙個s字串再進行遍歷操作;
而使用for (char& c : s)時直接引用原字串進行遍歷操作,由於複製乙個字串花費了大量的時間,所以第二種解法要快於第一種解法。
動態庫使用方法
動態庫api介紹 include void dlopen const char filename,intflag char dlerror void void dlsym void handle,const char symbol int dlclose void handle dlopen 以指定...
define使用方法及模板
define pi 3.1415926 define max a,b a b a b define a x x define b x x define c x x 如果我們假設x a,那麼a a 就是a,b a 就是 a c 1 就是 a 字串轉化用法 define to string s s 編譯...
動態語句的使用方法
雖然是 但經過鄙人親自操作,而後有感 生成測試表ta if not object id ta is null drop table ta go create table ta id int primary key,col1 int,col2 nvarchar 10 insert ta select ...