动态规划:两个数组的dp问题(C++)

news2024/12/23 16:28:53

动态规划:两个数组的dp问题

    • 前言
    • 两个数组的dp问题
      • 1.最长公共子序列(中等)
      • 2.不同的子序列(困难)
      • 3.通配符匹配(困难)
      • 4.正则表达式(困难)
      • 5.交错字符串(中等)
      • 6.两个字符串的最小ASCII删除和(中等)
      • 7.最长重复子数组(中等)

前言

动态规划往期文章:

  1. 动态规划入门:斐波那契数列模型以及多状态
  2. 动态规划:路径和子数组问题
  3. 动态规划:子序列问题
  4. 动态规划:回文串问题

两个数组的dp问题

1.最长公共子序列(中等)

链接:最长公共子序列

  • 题目描述
    在这里插入图片描述

  • 做题步骤

  1. 状态表示
    对于两个数组的dp,采用一维dp是没有办法清晰的表示状态的,故对于两个数组的dp我们通常采用二维数组

    故定义状态表示为dp[i] [j]:s1的[0,i]区间和s2的[0,j]区间之间的最长公共子序列

  2. 状态转移方程
    对s1的[0,i]区间和s2的[0,j]区间,我们分情况讨论:
    (1)s1[i] == s2[j],我们只需要知道s1的[0,i - 1]区间和s2的[0,j - 1]区间之间的最长公共子序列,然后加一即可,即dp[i] [j] = dp[i - 1] [j - 1] + 1。(比如s1 = "abc"和s2 = “akc”,就是"ab"和"ak"的最长公共子序列加1)

    (2)s1[i] != s2[j],这个这时最长公共子序列⼀定不会同时以s1[i]和s2[j]结尾
    ①有可能以s2[j]结尾,去s1的 [0, i - 1]以及s2的 [0, j] 区间内找:此时最大长度为dp[i - 1] [j]。(比如s1 = “ack”,s2 = “bc”)
    ②有可能以s1[i]结尾,去s1的[0, i]以及s2的 [0, j - 1] 区间内找:此时最大长度为dp[i] [j - 1]。(比如s1 = “ac”,s2 = “cb”)
    ③也有可能两者都不是结尾,但这个情况是包括在前两个情况中的,一定小于等于前两者。(比如s1 = “acd”,s2 = “aca”)
    对于(2)情况,dp[i] [j] = max(dp[i - 1] [j], dp[i] [j - 1])

  3. 初始化

在这里插入图片描述

  1. 填表顺序
    参照上面的图,填表顺序为行从上到下,每一行从左到右

  2. 返回值
    依据状态表示,返回值为dp[m] [n](m,n分别为s1、s2长度)。

  • 代码实现
class Solution {
public:
    int longestCommonSubsequence(string s1, string s2) {
        int m = s1.size(), n = s2.size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        //处理下标映射
        s1 = " " + s1, s2 = " " + s2;
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
            {         
                if(s1[i] == s2[j])
                    dp[i][j] =  dp[i - 1][j - 1] + 1;         
                else
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);               
            }     
        return dp[m][n];
    }
};

2.不同的子序列(困难)

链接:不同的子序列

  • 题目描述
    在这里插入图片描述

  • 做题步骤

  1. 状态表示
    这个题目虽然标的是困难,但是有前面的做题经验其实还好。
    对这种问题,我们采用二维表,定义状态表示为dp[i] [j]:t的[0, j]区间在s的[0, i]区间出现的方案个数

  2. 状态转移方程
    对s的[0,i]区间和t的[0,j]区间,我们分情况讨论:
    (1)s[i] == t[j]
    ①比如t = "rab"和s = “rabcb”,第一种同时选s[i]、t[j]为结尾,这个时候的方案数为t的[0, j - 1]区间在s的[0, i - 1]区间出现的方案数(ra在rabc中出现的次数),即dp[i - 1] [j - 1]。
    ②第二种是不同时选s[i]、t[j]为结尾,这个时候的方案数为t的[0, j]区间在s的[0, i - 1]区间出现的方案数(t = "rab"在s的"rabc"中出现的次数),即dp[i - 1] [j]。
    两种都符合要求:故(1)情况dp[i] [j] = dp[i - 1] [j] + dp[i - 1] [j - 1]

    (2)s[i] != t[j]
    这个时候只有一种选择,即(1)的②情况,故(2)情况dp[i] [j] = dp[i - 1] [j]

  3. 初始化
    这个题目的初始化和上一题相似,多开一行一列,把多的一行一列当作空串。其中当t为空串时在s中一定有一种方案(s也拿一个空串出来),故初始化第一列为1

  4. 填表顺序
    填表不明白参考第一题,填表顺序为行从上到下,每一行从左到右

  5. 返回值
    依据状态表示,返回值为dp[m] [n](m,n分别为s、t长度)。

  • 代码实现
class Solution {
public:
    int numDistinct(string s, string t) {
        int m = s.size(), n = t.size();
        //这个题目中间填表的时候会溢出,而且溢的不是一点点
        //不过溢出的部分不影响结果,用uint即可
        vector<vector<unsigned int>> dp(m + 1, vector<unsigned int>(n + 1));
        s = " " + s, t =  " " + t;  //处理下标映射
        for(int i = 0; i < m; i++)  dp[i][0] = 1;
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
            {
                dp[i][j] = dp[i - 1][j];
                if(s[i] == t[j])  //s[i] == t[j]会多一种选择
                    dp[i][j] += dp[i - 1][j - 1];                         
            }
        return dp[m][n];
    }
};

3.通配符匹配(困难)

链接:通配符匹配

  • 题目描述
    在这里插入图片描述

  • 做题步骤

  1. 状态表示
    依据前面的做题经验,我们定义一个二维表,定义状态表示为dp[i] [j]:p的[0, j]区间能否匹配s的[0, i]区间

  2. 状态转移方程
    对s的[0,i]区间和p的[0,j]区间,我们分情况讨论:
    (1)s[i] == p[j]或者p[j] == '?'时,dp[i] [j] = dp[i - 1] [j - 1],即只要p的[j - 1]区域能和s的[i - 1]区域匹配,p的[0, j]就可以和s的[0, i]匹配。(比如s = “abc”,p = “ab?”)

    (2)p[j] == ’ * ’ 的情况,这个时候有三种可能使得p[0, j]和s[0, i]匹配:
    p的[0, j]可以和s的[0, i - 1]匹配,p[j] == ’ * ’ 在表示原来的字符串基础上加上s[i]即可,即dp[i - 1] [j]为真dp[i] [j]为真。(比如s = “abc”,p = “a*”,"ab"和"a*"是匹配的)
    p的[0, j - 1]可以和s的[0, i]匹配, ’ * ’ 这个时候匹配空串即可,即dp[i] [j - 1]为真dp[i] [j]为真。(比如s = “ab”,p = “ab*”)
    ③p[0, j - 1]匹配和s的[0, i - 1],p[j] == ’ * ’ 去替换s[i],但这种情况实际是可以被归于第一种情况的,如果s[0, i - 1]和p[0, j - 1]匹配,那么s[0, i - 1]和p[0 , j]也一定会匹配,这个时候 ’ * ’ 做空字符串,即dp[i - 1] [j - 1]为真 == dp[i - 1] [j]为真

    以上情况只要一个为真dp[i] [j]就为真。

  3. 初始化
    和前面一样,为了避免越界以及方便初始化,我们引入空串的概念,多开一行和一列。
    ①其中两者都为空串可匹配,即dp[0] [0] = true。

    ②s为空串,p不为空串(第一行除去[0, 0])的时候如果p的[0, j]区间为连续的 ’ * ’ 也是可以匹配空串的,dp[0] [0……j] = true。([0, j]区间表示连续的 ’ * ’ )

    ③p为空串,s不为空串(第一列除去[0, 0]),这个时候不可能匹配,第一列除开[0][0]其它都初始化为false。

  4. 填表顺序
    填表不明白参考第一题,填表顺序为行从上到下,每一行从左到右

  5. 返回值
    依据状态表示,返回值为dp[m] [n](m,n分别为s、p长度)。

  • 代码实现
class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size(), n = p.size();
        s = " " + s, p = " " + p;   //处理下标映射
        //dp[i][j]:p的[0, j]区间能否匹配s的[0, i]区间
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));
        dp[0][0] = true;  
        for(int j = 1; j <=n; j++)  //初始化s为空串,p有连续'*'可匹配的情况
        {
            if(p[j] == '*')
                dp[0][j] = true;
            else
                break;  //出现非'*'直接结束循环,后面不可能匹配了
        }
        for(int i = 1; i <= m; i++)       
            for(int j = 1; j <= n; j++)
            {
                if(p[j] == '*')
                    dp[i][j] = dp[i - 1][j] || dp[i][j - 1];
                else if(s[i] == p[j] || p[j] == '?')
                    dp[i][j] = dp[i - 1][j - 1];
            }
        return dp[m][n];
    }
};

4.正则表达式(困难)

链接:正则表达式

  • 题目描述
    在这里插入图片描述

  • 做题步骤

  1. 状态表示
    有前面的做题经验,我们定义一个二维表,定义状态表示为dp[i] [j]:p的[0, j]区域能否匹配s的[0, i]区域

  2. 状态转移方程
    这个题目的重点:"a*"说明这个部分可以出现多次,也可以出现0次,即a表示空串,所以分析的时候应该把"字符 + "当作一个整体来考虑

    对s的[0,i]区间和p的[0,j]区间,我们分情况讨论:
    (1)s[i] == p[j]或p[j] == ’ . ’ ,只需要p的[0, j - 1]和s的[0, i - 1]匹配即可,即dp[i - 1] [j - 1]为真dp[i] [j]就为真。(比如s = "abc"和p = “ab.”)

    (2)p[j] == ’ * ’ 的情况,这个时候有三种可能使得p[0, j]和s[0, i]匹配:
    ①p[0, j - 2]和s[0, i]匹配,后面的"字符+"表示空串。即dp[i] [j - 2]为真dp[i] [j]就为真。(比如s = “abc”,p = “abcg*”,p后面的"g*"可以直接作空串)
    ②p[0, j]和s[0, i - 1]匹配,原本的"字符+"需要多表示一个字符。
    但这里多表示的字符是固定的,也就是说必须满足p[j - 1] == s[i] 或 p[j - 1] == ’ . ’ ,这个多表示的字符才能符合要求。即满足前面条件dp[i - 1] [j]为真dp[i] [j]就为真
    (比如s = “abbb”,p = “ab*”,其中"ab*"是可以匹配"abb"的,刚好"b*"多表示一个’ b ’ 符合匹配要求。如果s = "abbc"就p就无法匹配s了)

    以上情况只要一个为真dp[i] [j]就为真。

  3. 初始化
    为了避免越界已经方便初始化,我们引入空串的概念,多开一行一列。
    ①其中两者都为空串可匹配,即dp[0] [0] = true。

    ②当s为空串,p不为空串(第一行除去[0, 0])的时候如果p为连续的"字符 + * + 字符 + * ……",让这些"字符+ *"全都作空串,是可以匹配s的。即dp[0] [j] = true(j = 2; j <= n; j += 2)。

    ③p为空串,s不为空串(第一列除去[0, 0]),这个时候不可能匹配,第一列除开[0] [0]其它都初始化为false。

  4. 填表顺序
    填表不明白参考第一题,填表顺序为行从上到下,每一行从左到右

  5. 返回值
    依据状态表示,返回值为dp[m] [n](m,n分别为s、p长度)。

  • 代码实现
class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size(), n = p.size();
        //处理下标映射
        s = " " + s,  p = " " + p;
        //dp[i][j]:p的[0,j]区域能否和s的[0,i]区域匹配
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));
        dp[0][0] = 1;  //空串可以匹配空串
        for(int j = 2; j <= n; j += 2)  //s为空串时p为连续的"字符 + *"是可以匹配的
        {
            if(p[j] == '*') 
                dp[0][j] = true;
            else
                break;
        }
       
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
            {
                if(p[j] == '*')
                {
                    dp[i][j] = dp[i][j-2] || (p[j-1] == '.' || p[j-1] == s[i]) && dp[i-1][j];
                }
                else if(s[i] == p[j] || p[j] == '.')
                {
                    dp[i][j] = dp[i - 1][j - 1];
                }
            }
        return dp[m][n];
    }
};

5.交错字符串(中等)

链接:交错字符串

  • 题目描述
    在这里插入图片描述

  • 做题步骤

  1. 状态表示
    有前面的做题经验,我们定义一个二维表,定义状态表示为dp[i] [j]:s1的[0, i]区间和s2的[0, j]区间能否交错组成s3的[0, i + j]区间

  2. 状态转移方程
    对s1的[0,i]区间和s2的[0,j]区间能否交错组成s3的[0, i + j]区间,我们分情况讨论:
    (1)s1[i] == s3[i + j]。这个时候只要s1的[0, i - 1]区间和s2的[0, j]区间可以组成s3的[0,i + j - 1]区间即真,即dp[i] [j] = (s1[i] == s3[i + j] && dp[i - 1] [j])

    (2)s2[j] == s3[i + j]。这个时候只要s1的[0, i]区间和s2的[0, j - 1]区间可以组成s3的[0,i + j - 1]区间即真,即dp[i] [j] = (s2[j] == s3[i + j] && dp[i] [j - 1])

    以上情况只要一个为真dp[i] [j]就为真。

  3. 初始化
    为了避免越界以及方便初始化,我们引入空串的概念,多开一行一列。
    ①其中s1和s2都为空串可以组成空串s3,即dp[0][0] = true。

    ②当s1为空串,s2不为空串(第一列除去[0, 0])的时候可以由s2单独组成s3,前提是相等。即dp[0] [j] = true([1, j]区间s2与s3相等)。

    ③当s2为空串,s1不为空串(第一行除去[0, 0])的时候可以由s1单独组成s3,前提是相等。即dp[i] [0] = true([1, i]区间s1与s3相等)。

  4. 填表顺序
    填表不明白参考第一题,填表顺序为行从上到下,每一行从左到右

  5. 返回值
    依据状态表示,返回值为dp[m] [n](m,n分别为s1、s2长度)。

  • 代码实现
class Solution
{
public:
    bool isInterleave(string s1, string s2, string s3) 
    {
        int m = s1.size(), n = s2.size();
        if(m + n != s3.size()) return false;  //两者相加比s3长度小,一定没办法组成的
        s1 = " " + s1, s2 = " " + s2, s3 = " " + s3;  //处理下标映射
        //dp[i][j]:s1的[1,i]区间和s2的[1,j]区间能否交错组成s3的[1,i+j]区间
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));
        dp[0][0] = true;
        for(int j = 1; j <= n; j++) // 初始化第⼀⾏,即s1为空,s2单独组成s3
        {
            if(s2[j] == s3[j]) dp[0][j] = true;
            else break;
        }
        for(int i = 1; i <= m; i++) // 初始化第⼀列,即s2为空,s1单独组成s3
        {
            if(s1[i] == s3[i]) dp[i][0] = true;
            else break;
        }
        
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
                dp[i][j] = (s1[i] == s3[i + j] && dp[i - 1][j])
                        || (s2[j] == s3[i + j] && dp[i][j - 1]);        
        return dp[m][n];
    }
};

6.两个字符串的最小ASCII删除和(中等)

链接:两个字符串的最小ASCII删除和

  • 题目描述
    在这里插入图片描述

  • 做题步骤

  1. 状态表示
    有前面的做题经验,我们定义一个二维表,定义状态表示为dp[i] [j]:s1的[0, i]区间和s2的[0, j]区间要达到相同的最小删除消耗

  2. 状态转移方程
    对s1的[0,i]区间和s2的[0,j]区间如何相同,我们分情况讨论:
    (1)s1[i] == s2[j]时,只需要让s1的[1, i - 1]和s2[1, j - 1]相同,即dp[i] [j] = dp[i - 1] [j - 1]

    (2)s1[i] != s2[j]时,有两种选择:
    ①让s1的[1, i - 1]和s2的[1, j]相同,把多余的s1[i]删除,即dp[i] [j] = dp[i - 1] [j] + s1[i]
    ②s1的[1, i]和s2的[1, j -1]相同,把多余的s2[j]删除,即dp[i] [j] = dp[i] [j - 1] + s2[j]
    取①②情况的最小值即可,即(2)情况dp[i][j] = min(dp[i] [j - 1] + s2[j], dp[i - 1] [j] + s1[i])

    这里提一下(1)情况的消耗是一定小于等于(2)的消耗,比如我一个短串和一个长串达到相等的消耗了x。现在我在短串后面加一些字符,想达到相等的话消耗一定会大于等于x。

  3. 初始化
    为了避免越界以及方便初始化,我们引入空串的概念,多开一行一列。
    ①当s1和s2都为空串,消耗为0,即dp[0] [0] = 0。

    ②当s1为空串,s2不为空串(第一列除去[0, 0])的时候s2必须全部删除一直到为空串。即dp[0] [j] = dp[0] [j - 1] + s2[j] (j = 1; j <= n; j++)。

    ③当s2为空串,s1不为空串(第一行除去[0, 0])的时候s1必须全部删除一直到为空串。即dp[i] [0] = dp[i - 1] [0] + s1[i] (i = 1; i <= m; i++)。

  4. 填表顺序
    填表不明白参考第一题,填表顺序为行从上到下,每一行从左到右

  5. 返回值
    依据状态表示,返回值为dp[m] [n](m,n分别为s1、s2长度)。

  • 代码实现
class Solution {
public:
    int minimumDeleteSum(string s1, string s2) {
        int m = s1.size(), n = s2.size();
        s1 = " " + s1, s2 = " " + s2;   //处理下标映射
        //dp[i][j]:s1的[1,i]区间和s2的[1,j]区间要达到相同的最小删除消耗
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        //s1为空串,s2要删除为空串的最小消耗
        for(int j = 1; j <= n; j++)
            dp[0][j] = dp[0][j - 1] + s2[j];
        //s2为空串,s1要删除到空串的最小消耗
        for(int i = 1; i <= m; i++)
            dp[i][0] = dp[i - 1][0] + s1[i];

        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
            {
                if(s1[i] == s2[j])
                    dp[i][j] = dp[i - 1][j - 1];
                else
                    dp[i][j] = min(dp[i][j - 1] + s2[j], dp[i - 1][j] + s1[i]);
            }
        return dp[m][n];
    }
};

7.最长重复子数组(中等)

链接:最长重复子数组

  • 题目描述
    在这里插入图片描述

  • 做题步骤

  1. 状态表示
    这个题不难,但是注意它是子数组而不是子序列,我们用前面的方式定义状态表示是会出错的,比如我定义状态表示为dp[i] [j]:n1的[0, i]区间与n2的[0, j]区间中的公共最长子数组长度。
    拿n1 = [3, 1, 1]和n2 = [1, 0, 1]举例,n1的[3, 1]区间和n2的[1, 0]区间公共最长子数组长度为1,当n1[2] == n2[2]的时候,公共最长子数组是没办法算的,你想dp[i - 1][j - 1] + 1是绝对不行的,因为n1[2]和n2[2]不一定能接在这个最长子数组后面,子数组必须是连续的!!!

    前面以区间为关注对象,没办法推导状态转移方程,那我们就以n1[i]和n2[j]为子数组结尾进行分析。
    我们定义一个二维表,定义状态表示为dp[i] [j]:同时以n1的i位置和n2的j位置结尾的公共最长子数组长度

  2. 状态转移方程
    对n1[i]和n2[j],我们分情况讨论:
    (1)n1[i] == n2[j]时,可以同时接在以n1[i - 1]和n2[j - 1]为结尾的公共最长子数组后面,长度加1,即dp[i] [j] = dp[i - 1] [j - 1] + 1。

    (2)n1[i] != n2[j]时,同时以n1[i]和n2[j]为结尾的公共最长子数组不存在,即dp[i] [j] = 0。

  3. 初始化
    为了避免越界,我们多开一行一列,dp数组下标从1开始,多出来的一行一列初始化为0即可。(注意处理与n1和n2数组的下标映射,因为n1和n2数组是从下标0开始的)

  4. 填表顺序
    填表顺序为行从上到下,每一行从左到右

  5. 返回值
    没法直接确定最长子数组的结尾,所以一边dp一边更新最大值

  • 代码实现
class Solution {
public:
    int findLength(vector<int>& n1, vector<int>& n2) {
        int m = n1.size(), n = n2.size();
        //dp[i][j]表示以nums1的i位置和nums2的j位置结尾的公共最长子数组长度
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        int ret = 0;
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
            {
                if(n1[i - 1] == n2[j - 1])  //注意下标映射
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                ret = max(ret, dp[i][j]);
            }
        return ret;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1054410.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go结构体深度探索:从基础到应用

在Go语言中&#xff0c;结构体是核心的数据组织工具&#xff0c;提供了灵活的手段来处理复杂数据。本文深入探讨了结构体的定义、类型、字面量表示和使用方法&#xff0c;旨在为读者呈现Go结构体的全面视角。通过结构体&#xff0c;开发者可以实现更加模块化、高效的代码设计。…

背包问题

目录 开端 01背包问题 AcWing 01背包问题 Luogu P2925干草出售 Luogu P1048采药 完全背包问题 AcWing 完全背包问题 Luogu P1853投资的最大效益 多重背包问题 AcWing 多重背包问题 I AcWing 多重背包问题 II Luogu P1776宝物筛选 混合背包问题 AcWing 混合背包问题…

JavaSE学习之--抽象类和接口

&#x1f495;"没有眼泪我们就会迷路&#xff0c;彻底变成石头&#xff0c;我们的心会变成冰凌&#xff0c;吻会变成冰块。"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;JavaSE学习之--抽象类和接口 一.抽象类 1.抽象类的定义 我们知道&#x…

数仓精品理论-做大数据还有没有前途?

数仓精品理论-做大数据还有没有前途&#xff1f; 做大数据还有没有前途&#xff1f;大数据三要三不要我来讲讲大数据前景 做大数据还有没有前途&#xff1f; 先说&#xff0c;答案是肯定的&#xff0c;但一定要记住三要三不要。 datapulse官网&#xff1a; github:https://data…

cesium gltf控制

gltf格式详解 glTF格式本质上是一个JSON文件。这一文件描述了整个3D场景的内容。它包含了对场景结构进行描述的场景图。场景中的3D对象通过场景结点引用网格进行定义。材质定义了3D对象的外观,动画定义了3D对象的变换操作(比如选择、平移操作)。蒙皮定义了3D对象如何进行骨骼…

黑豹程序员-架构师学习路线图-百科:HTML-网页三剑客

为什么需要HTML 在网站技术发达之前&#xff0c;千年来我们获取信息是通过书籍。电脑流行后我们看文章、小说通过txt文件。看图通过单独的图片流量工具看单个的图片文件。 而HTML把文字和图片一起展示&#xff0c;让今天的电子书成为可能。 另外一点&#xff0c;我们的信息是…

【操作系统】了解Linux操作系统中PCB进程管理模块与进程PID

本篇要分享的内容是有关于操作系统中进程的内容。 目录 1.进程的简单理解 2.了解task_struct&#xff08;进程控制模块&#xff09;内容分类 3.task_struct&#xff08;进程控制模块&#xff09;中的PID 4.调用查看PID的函数 1.进程的简单理解 首先我们需要理解的是什么是…

简单讲解 glm::mat4

文章目录 前言一、下载glm库二、基本数学知识1. 三维中的 4 x 4 矩阵2.旋转3. 位移4. 缩放5. 组合 三、行向量或列向量四、总结 前言 glm库是OpenGL的官方数学库&#xff0c;里面内置多种跟几何变换相关的函数&#xff0c;熟练掌握glm库可以省下很多麻烦。 因为最近在项目中主…

鞋类 整鞋试验方法 剥离强度

声明 本文是学习GB-T 3903.3-2011 鞋类 整鞋试验方法 剥离强度. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 GB/T 3903 的本部分规定了整鞋鞋底与鞋帮或外底与外中底之间剥离强度的试验方法。 本部分适用于采用模压、硫化、注塑、灌注、胶…

暴力破解及验证码安全

1.暴力破解注意事项 1、破解前一定要有一个有郊的字典&#xff08;Top100 TOP2000 csdn QQ 163等密码&#xff09; https://www.bugku.com/mima/ 密码生成器 2、判断用户是否设置了复杂的密码 在注册页面注册一个,用简单密码看是否可以注册成功 3、网站是…

Jenkins集成AppScan实现

一、Jenkins上安装插件 在Jenkins里安装以下插件 ibm-security-appscanstandard-scanner 二、打开AppScan 1、配置需要扫描的地址 配置需要扫描的地址 2、记录好要扫描的URL登录序列 记录好要扫描的URL登录序列 3、导出要扫描的URL登录序列设置 导出要扫描的URL登录序列设置 三…

C程序设计内容与例题讲解 -- 第四章--选择结构程序设计(第五版)谭浩强

前言&#xff1a;在第三章我们介绍了顺序结构程序设计。在顺序结构中&#xff0c;各个语句是按自上而下的顺序执行的&#xff0c;执行完上一个语句就自动执行下一个语句&#xff0c;是无条件的&#xff0c;不必做任何判断。是这最简单的程序结构。实际上&#xff0c;在很多情况…

IDEA 配置 Maven(解决依赖下载缓慢)

IDEA 配置 Maven&#xff08;解决依赖下载缓慢&#xff09; 这一篇主要介绍 Maven 的基本用法。等我之后学习到框架知识时&#xff0c;会完善此部分内容。 一、Maven 简介 Maven 是专门用于管理和构建 Java 项目的工具&#xff0c;Apache Maven 是一个项目管理和构建工具&#…

ali内核服务器搭建Linux版本的小皮面板(微调)

一、搭建小皮面板 windows版本的小皮面板我们经常使用,早就熟悉了搭建和配置 那么这里我们就来使用Linux版本的小皮面板,看看如何进行操作 安装网址: https://www.xp.cn/linux.html 这里根据自己的操作系统选择合适的命令 我使用的是kali搭建,因此选择Debian安装脚本 注意:…

28270-2012 智能型阀门电动装置 学习笔记

声明 本文是学习GB-T 28270-2012 智能型阀门电动装置. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了智能型阀门电动装置(以下简称智能电装)的术语、技术要求、试验方法、检验规则、标 志、包装、运输和贮存条件等。 本标准适…

24Hibench

1. Hibench 官网 ​ HiBench is a big data benchmark suite that helps evaluate different big data frameworks in terms of speed, throughput and system resource utilizations. It contains a set of Hadoop, Spark and streaming workloads, including Sort, WordCou…

国庆放假作业2

1、select实现服务器并发 #include <myhead.h>#define PORT 7373 #define IP "192.168.1.9"int main(int argc,const char *argv[]) {//创建报式套接字int sfdsocket(AF_INET,SOCK_STREAM,0);if(sfd<0){ERR_MSG("socket error");return -1;}prin…

MATLAB与Python:优势与挑战

本文旨在探讨MATLAB与Python在特定领域内的使用情况&#xff0c;并分析两者之间的优势和挑战。 MATLAB和Python都是流行的编程语言&#xff0c;广泛应用于科学计算、数据分析和机器学习等领域。在某些领域&#xff0c;如航空航天工程、自动化和电子工程嵌入式系统开发等&#…

【分布式事务】

文章目录 解决分布式事务的思路seata四种模式1. XA模式2. AT模式AT模式与XA模式的区别是什么&#xff1f;脏写问题 3. TCC模式事务悬挂和空回滚 4. SAGA模式 四种模式对比口述AT模式与TCC模式高可用 什么是分布式事务&#xff1f; 分布式事务&#xff0c;就是指不是在单个服务或…

Arduino ESP32/ESP8266 +ST7735 1.8“tft中秋小时钟

Arduino ESP32 ST7735 1.8"tft中秋小时钟 &#x1f33c;原作者B站视频&#xff1a; ESP32中秋小时钟&#xff0c;表盘自动切换&#xff0c;代码开源&#xff0c;原图可下载&#xff08;案例应用&#xff09; &#x1f39e;tft ST7735 128160 1.8" 显示效果:(由于原作…