1. 程式人生 > >LeetCode-【動態規劃】- 一和零

LeetCode-【動態規劃】- 一和零

在計算機界中,我們總是追求用有限的資源獲取最大的收益。

現在,假設你分別支配著 m 個 0 和 n 個 1。另外,還有一個僅包含 0 和 1 字串的陣列。

你的任務是使用給定的 m 個 0 和 n 個 1 ,找到能拼出存在於陣列中的字串的最大數量。每個 0 和 1 至多被使用一次

注意:

  1. 給定 0 和 1 的數量都不會超過 100
  2. 給定字串陣列的長度不會超過 600

示例 1:

輸入: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3
輸出: 4

解釋: 總共 4 個字串可以通過 5 個 0 和 3 個 1 拼出,即 "10","0001","1","0" 。

示例 2:

輸入: Array = {"10", "0", "1"}, m = 1, n = 1
輸出: 2

解釋: 你可以拼出 "10",但之後就沒有剩餘數字了。更好的選擇是拼出 "0" 和 "1" 。

題解:乍看本題,毫無思路,不過如果你熟悉二維費用的揹包問題<傳送門>(相關題目洛谷P1507),這道題目就變得簡單了,好吧,假設你已經看懂基於二維費用的揹包問題,那對應本題,0和1的數目分別對應的是擁有的資源,能組成的數字個數就是揹包能裝下的最大價值,跟根據二維費用的揹包問題的動態轉移方程,dp[i][j]=max(dp[i][j],d[i-s1[1]][j-s2[i]]+1);在這裡dp[i][j]表示的意思是花費i和j數目的兩種資源能獲得的最大價值也就是本題中能組成的最大數字數目,s1[i]表示組成當前數字需要的0的個數,s2[i]表示組成當前數字需要的1的個數,整個動態轉移方程基於是否組成當前數字來判斷,d[i-s1[1]][j-s2[i]]+1就表示的是組成當前數字,d[i-s1[1]][j-s2[i]]表示沒有組成當前數字時最大最優解,再加上當前數字就是組成當前數字之後的解,在進行比較確定是都是最優解。

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        int l=strs.length;
        int[][] dp=new int[m+1][n+1];
        for(String str:strs){
            int z=0,o=0;
            for(int i=0;i<str.length();i++){
                if(str.charAt(i)=='0')
                    z++;
                else
                    o++;
            }
            for(int i=m;i>=z;i--){
                for(int j=n;j>=o;j--){
                    dp[i][j]=Math.max(dp[i][j],dp[i-z][j-o]+1);
                }
            }
        }
        return dp[m][n];
    }
}