[Dynamic Programming Algorithm Exercise] day17


Two-dimensional cost knapsack problem:

1. 474. Ones and zeros

1. Introduction to the topic

474. Ones and Zeros
You are given a binary string array strs and two integers m and n.
Please find and return the length of the largest subset of strs, which contains at most m 0s and n 1s.
A set x is a subset of the set y if all elements of x are also elements of y.
Insert image description here

2. Problem-solving ideas

3.Code

class Solution {
    
    
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
    
    
        vector<int> v(m + 1, 0);//初始化
        vector<vector<int>> dp(n + 1, v);//dp[j][k]表示满足“最多”有j个1和k个0的strs的最大子集的长度(最多:说明并不一定要求放满,因此不用判断dp[j - v1[i]][k - v0[i]]是否存在)
        vector<int> v1(strs.size(), 0);//字符串中1的个数
        vector<int> v0(strs.size(), 0);//字符串中0的个数
        for(int i = 0;i < strs.size(); ++i)//将字符串中的1和0分别存放
        {
    
    
            for(int j = 0;j < strs[i].size(); ++j)
            {
    
    
                if(strs[i][j] == '1') v1[i]++;
                else v0[i]++;
            }
        }
        for(int i = 0;i < strs.size(); ++i)
        {
    
    
            //题意可知这些字符串每个都只能使用一次,属于01背包问题,因此背包的遍历顺序是从后往前
            for(int j = n;j >= v1[i]; --j)
            {
    
    
                for(int k = m;k >= v0[i]; --k)
                {
    
    
                    dp[j][k] = max(dp[j - v1[i]][k - v0[i]] + 1, dp[j][k]);//放这个字符串和不放
                }
            }
        }
        return dp[n][m];//如果凑不出满足需要的子集,则返回0
    }
};

4. Running results

Insert image description here

2. 879. Profit plan

1. Introduction to the topic

879. Profit plan
There are n employees in the group, and they can complete various tasks to create profits.
The i-th job will generate profit[i], and it requires the participation of group[i] members. If a member is involved in one of the tasks, he cannot be involved in the other.
Any subset of work that generates at least minProfit profit is called a profit plan. And the total number of working members is at most n.
How many plans are there to choose from? Because the answer is large, the result is returned modulo 10^9 + 7.
Insert image description here

2. Problem-solving ideas

3.Code

class Solution {
    
    
public:
    int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
    
    
        int mod = 1e9 + 7;
        //由题意可知,这是一个01背包问题中的二维费用背包问题(二维指的是人数和利润这两个维度)
        vector<int> v(minProfit + 1, 0);
        vector<vector<int>> dp(n + 1, v);//dp[j][k]表示至少产生k的利润,最多提供j个员工时的计划数
        //初始化利润为0时的dp表
        for(int j = 0;j <= n; ++j)//无论人数是多少,我们都可以找到一个空集的方案
        {
    
    
            dp[j][0] = 1;
        }
        for(int i = 0;i < group.size(); ++i)
        {
    
    
            for(int j = n;j >= group[i]; --j)//(人数绝对不能是小于0的,因此j要大于等于group[i])
            {
    
    
                for(int k = minProfit;k >= 0; --k)//利润可以等于0,但是正常情况下利润是不小于0的,因此k - profit要和0取较大值
                {
    
    
                    dp[j][k] += dp[j - group[i]][max(0, k - profit[i])];//求计划数(求组合数,用+)
                    dp[j][k] %= mod;
                }
            }
        }
        return dp[n][minProfit];
    }
};

4. Running results

Insert image description here

Problems that seem to be included but not included:

3. 377. Combination sum IV

1. Introduction to the topic

377. Combining Sum IV
gives you an array nums consisting of different integers, and a target integer target. Please find and return the number of element combinations whose sum is target from nums.
The question data ensures that the answer fits within the 32-bit integer range.
Insert image description here
Insert image description here

2. Problem-solving ideas

3.Code

class Solution {
    
    
public:
//1.多重背包问题:遍历背包要从左往右
//2.本质是求排列个数的问题:对顺序有要求,则先遍历背包再遍历物品
    int combinationSum4(vector<int>& nums, int target) {
    
    
        vector<int> dp(target + 1, 0);//dp[j]表示凑成总和为j的元素组合个数
        dp[0] = 1;
        for(int j = 0;j <= target; ++j)
        {
    
    
            for(int i = 0;i < nums.size(); ++i)
            {
    
    
                if(j >= nums[i] && dp[j] < INT_MAX - dp[j - nums[i]])
                dp[j] += dp[j - nums[i]]; //计算组合数、排列数用+
            }
        }
        return dp[target];
    }
};

4. Running results

Insert image description here

4. 96. Different binary search trees

1. Introduction to the topic

96. Different binary search trees.
Given an integer n, how many binary search trees are there that consist of exactly n nodes and have different node values ​​from 1 to n? Returns the number of binary search trees that satisfy the question.
Insert image description here

2. Problem-solving ideas

3.Code

class Solution {
    
    
public:
    int numTrees(int n) {
    
    
        if(n == 0 || n == 1) return 1;
        if(n == 2) return 2;
        vector<int> dp(n + 1, 0);//dp[i]表示当有i个节点时,它所能形成的二叉搜索树的种数
        dp[0] = 1;//空树
        dp[1] = 1;//只有一个根节点
        dp[2] = 2;
        for(int i = 3;i <= n; ++i)
        {
    
    
            int left = i - 1, right = 0;//left是左子树的节点个数,right是右子树的节点个数
            while(left >= 0)
            {
    
    
                dp[i] += dp[left--] * dp[right++];
            }
        }
        return dp[n];
    }
};

4. Running results

Insert image description here


Summarize

Today is the 17th day of algorithm practice.
Be encouraged in time, time waits for no one , and the dynamic programming algorithm training has come to an end.
Source: LeetCode, the copyright belongs to LeetCode.
If this article has inspired you, I hope you can support the author more, thank you all!

Guess you like

Origin blog.csdn.net/xjjxjy_2021/article/details/131476769