动态规划刷题总结(入门)

目录

什么是动态规划算法

如何判断题目中将使用动态规划算法?

动态规划题目做题步骤

动态规划题目解析

泰波那契数模型

第 N 个泰波那契数

三步问题 

使用最小花费爬楼梯 

路径问题 

不同路径 

不同路径 Ⅱ 

珠宝的最高价值 

下降最短路径和 

地下城游戏 

简单多状态问题

按摩师

打家劫舍 Ⅱ 

删除并获得点数 

粉刷房子 

复杂多状态问题

买卖股票的最佳时机含冷冻期

买卖股票的最佳时机含手续费

买卖股票的最佳时机 Ⅲ 

买卖股票的最佳时机 Ⅳ 

子数组问题 

最大子数组和

环形子数组的最大和 

乘积最大数组


什么是动态规划算法

动态规划(Dynamic programming)是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的算法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。

如何判断题目中将使用动态规划算法?

当分析问题的过程中,出现重复子问题,例如下面的问题:

三步问题

小孩多次重复上楼这个动作,问最多的方式

使用最小花费爬楼梯

要计算出达到楼顶的最低花费,先要求出 楼顶 - 1  或 楼顶 - 2  位置的最低花费 

不同路径

需要到达星星位置,就要先到达 1/2 的位置,要达到 1/2 的位置,需要先达到 1/2 的各自得左边或上边,依次类推......

最大子数组和

以 i 位置为结尾的数组中和最大的子数组,与以 i - 1位置为结尾的数组中和最大的子数组也由一定的关系,但关系或许不是绝对的,需要分析

动态规划题目做题步骤

动态规划类题目做题步骤一般分为 5 步

  • 状态表示

将需要的状态填入 dp 表中,这个状态一般是根据 题目要求 + 经验得出的。其中,线性 dp 表填 dp[i] 的经验为:以 i 位置为结尾, +(题意)或者 以 i 位置为开头,+ (题意)这里的题意,一般指题目中要求的东西。比如:使用最小花费爬楼梯问题中,dp[i] 就表示:爬到 i 位置时的最小花费;最大子数组和问题中,dp[i] 就表示以 i 位置为结尾的数组中最大的和

当然,dp 表也有可能是二维,甚至三维,具体需看题意,比如,不同路径中就需要 dp[i][j] 表示走到坐标为 [i, j] 位置时的路径数。

  • 状态转移方程

状态转移方程就是填 dp 表的关键,通俗的来说就是 dp[i] 等于什么,通过距离 i 位置最近的一步,来划分问题,如通过 dp[i - 1]、dp[i + 1]、dp[i - 2] 等等,如果状态转移方程写不出来,就要思考状态表示的正确性了。

  • 初始化

初始化 dp 数组,是为了防止填写 dp 表的时候发生越界。

  • 确定填表顺序

有的 dp表是从坐往右依次填,有的是从右往左依次填,取决于定义 dp 表时的状态表示。

  • 确定返回值

既然选择了使用动态规划解决这道问题,那么最终答案一定会直接或间接通过 dp 表产生!

动态规划题目解析

动态规划算法写代码的步骤比较固定:

  • 创建 dp 表
  • 初始化(保证填表的时候不越界)
  • 填表顺序及填表,保证填当前状态的时候,所需要的状态已经计算过了
  • 返回值

将 dp 表多开一列,一般是为了方便初始化,但多开一列后要注意原数组的下标需要与 dp 表有对应关系,再一个就是多开的那一列填的值必须保证 dp 表的填写正确!

泰波那契数模型

第 N 个泰波那契数

第 N 个泰波那契数

这道题是动态规划的基础,一定要好好理解这道题目!

class Solution {
public:
    int tribonacci(int n) {
        vector<int> dp(n + 1); // dp[i] 表示第 i 个泰波那契数列
        if(n == 0) return 0;
        if(n == 1|| n == 2) return 1;
        dp[0] = 0, dp[1] = 1, dp[2] = 1;
        // 由题意得:状态转移方程为 :dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
        for(int i = 3; i <= n; i++)
        {
            dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
        }
        return dp[n];
    }
};

三步问题 

三步问题

 泰波那契数模型

class Solution {
public:
    int waysToStep(int n) {
        const int MOD = 1e9 + 7;
        vector<int> dp(n + 1);
        // 初始化 dp 表,防止越界
        if(n == 1) return 1;
        if(n == 2) return 2;
        if(n == 3) return 4;
        dp[1] = 1, dp[2] = 2, dp[3] = 4;
        for(int i = 4; i <= n; i++)
        {
            dp[i] = ((dp[i - 1] + dp[i - 2])%MOD + dp[i - 3])%MOD;
        }
        return dp[n];
    }
};

使用最小花费爬楼梯 

使用最小花费爬楼梯

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n = cost.size();
        vector<int> dp(n);
        // dp[i] 表示以 i 位置为起点,到达楼顶的最小花费
        dp[n - 1] = cost[n - 1], dp[n - 2] = cost[n - 2];
        for(int i = n - 3; i >= 0; i--)
        {
            dp[i] = min(cost[i] + dp[i + 1], cost[i] + dp[i + 2]);
            //可以从 i - 1 位置或者 i - 2 位置到达 i 位置,取其中花费最小的
        }
        return min(dp[0], dp[1]);
    }
};

路径问题 

不同路径 

不同路径

使用二维 dp 表解决,只需要处理好初始化即可! 

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        dp[0][1] = 1; // 初始化,其余多开的地方全部为 0 
        for(int i = 1; i <= m; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                // dp[i][j] 表示走到走到 i 行 j 列为结尾的路径总数(加上一行一列的情况下)
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m][n];
    }
};

不同路径 Ⅱ 

 不同路径 II

这道题目相比于 不同路径 ,在方格中添加了障碍物,一但在路上遇到了障碍物,那么这条路就走不通了,这个 i,j 位置的 dp表的值就要置 0,并且 i, j 位置的 dp 值会一直影响后面的 dp 值,最终影响最终结果! 

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        dp[0][1] = 1;
        for(int i = 1; i <= m; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                if(obstacleGrid[i - 1][j - 1]) dp[i][j] = 0;
            }
        }  
        return dp[m][n];
    }
};

珠宝的最高价值 

珠宝的最高价值

这道题目的思路其实也挺简单的,相对于普通的二维 dp 中加入了一次判断大小的过程。

class Solution {
public:
    int jewelleryValue(vector<vector<int>>& frame) {
        int m = frame.size();
        int n = frame[0].size();
        // dp[i][j]为加上扩展的数组,到达第第 i 行,第 j 列时的最大价值
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));       
        for(int i = 1; i <= m; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + frame[i - 1][j - 1]; 
            }
        }
        return dp[m][n];
    }
};

下降最短路径和 

 下降路径最小和

这道题就要认真对 dp 表多开的那一列做初始化了!但如果不多开一列的话,边界条件可能会更难处理。为了在状态转移方程中求最小值的时候不被多开的那一列干扰,可以初始化为 INT_MAX

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 2));
        for(int i = 1; i <= m; i++) dp[i][0] = INT_MAX; // 初始化
        for(int i = 1; i <= m; i++) dp[i][n + 1] = INT_MAX; 
        for(int i = 1; i <= m; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j + 1])) + matrix[i - 1][j - 1];
            }
        }
        int min_path = INT_MAX;
        for(int j = 1; j <= n; j++)
        {
            if(dp[m][j] < min_path) min_path = dp[m][j];
        }
        return min_path;
    }
};

地下城游戏 

地下城游戏

这道题就采用了以 i,j 位置为起点的做法,这种做法比较方便计算。当然也可以使用以 i,j 位置为终点的 dp 思路,但需要开两个 dp 表,而且处理起来比较的复杂,不推荐。地下城游戏 

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon){
        int m = dungeon.size();
        int n = dungeon[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        // dp[i][j] 表示从 [i,j] 位置过后,到达终点所需要的最小健康点数
        for(int i = 0; i <= m; i++) dp[i][n] = INT_MAX;
        for(int j = 0; j <= n; j++) dp[m][j] = INT_MAX;
        dp[m][n -1] = dp[m - 1][n] = 1; // 保证计算出 i, j 位置救到公主的时候,起码要有 1 滴血
        for(int i = m -1; i >= 0; i--)
        {
            for(int j = n - 1; j >= 0; j--)
            {
                dp[i][j] = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
                dp[i][j] = max(1, dp[i][j]);
                // 如果 dp[i][j] 计算下来小于 0 ,说明后面有大血包,以至于在当前位置血量为负都行,但这是不符合游戏规则的
                // 所以到 i,j 位置时,起码得有 1 健康值 
            }
        }
        return dp[0][0];
    }
};

简单多状态问题

多状态问题,即 dp[i] 位置的状态,可能不只有一种,可能有多种情况,这些情况都要考虑进去!

按摩师

按摩师

dp[i] 的状态表示,填写都需要经过多方面思考。 

class Solution {
public:
    int massage(vector<int>& nums) {
        int n = nums.size();
        if(n == 0) return 0;
        vector<int> dpf(n), dpg(n);
        // dpf[i] 表示选择到 i 位置的时候,这个值 选, 得到的最大时长
        // dpg[i] 表示选择到 i 位置的时候,这个值不选,得到的最大时长
        dpf[0] = nums[0], dpg[0] = 0;
        for(int i = 1; i < n; i++)
        {
            dpf[i] = dpg[i - 1] + nums[i];
            dpg[i] = max(dpf[i - 1], dpg[i - 1]);
            // dpg[i] i 位置不选, i - 1 位置也可能不选也可能选 ,看哪个值最大就选哪个
        }
        return max(dpf[n - 1], dpg[n - 1]);
    }
};

打家劫舍 Ⅱ 

 打家劫舍 II

这道题的多种状态为:小偷是否偷第一间房,如果他偷了第一间,那就不能偷第二间,最后一间,所以只需要在 [3, n - 1] 之间找出最高金额,再加上第一间的金额即可;如果他没有偷第一间,那就是再 [2,n] 之间找出最高金额,最后再找出求出的这两个最高金额中最大的那个即可。

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        // 两种状态计算的方式相同,找出最大的那个即可!
        return max(nums[0] + _rob(nums, 2, n - 2), _rob(nums, 1, n - 1));
    }
    int _rob(vector<int>& nums, int left, int right)
    {
        if(left > right) return 0;
        int n = nums.size();
        vector<int> f(n); // 表示偷的 dp 表
        vector<int> g(n); // 表示不偷的 dp 表
        f[left] = nums[left];
        for(int i = left + 1; i <= right; i++)
        {
            // 两表之间需要相互计算,因此需要一起填表
            f[i] = g[i - 1] + nums[i];
            g[i] = max(f[i - 1], g[i - 1]);
        }
        return max(f[right], g[right]);
    }
};

删除并获得点数 

删除并获得点数

先排序,找出最大的数,并将所有的数映射到数组,再利用“打家劫舍”的多状态思路解决问题。

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int n = *(nums.end() - 1); // 求出 nums 中最大的元素,方便开 arr 数组
        vector<int> arr(n + 1, 0);  // 相当于将点数相邻的计数并放在一起了
        for(auto x: nums) arr[x] += x; // 将 x 的 '和' 全部映射在 arr 数组里
        // 利用 “打家劫舍” 的思路, 求出能获得的最大点数
        vector<int> f(n + 1); // 获得这个位置的点数,并不获得相邻位置的点数
        vector<int> g(n + 1); // 不获得这个位置的点数
        for(int i = 1; i <= n; i++)
        {
            f[i] = g[i - 1] + arr[i];
            g[i] = max(g[i - 1], f[i - 1]);
        }
        return max(f[n], g[n]);
    }
};

粉刷房子 

粉刷房子

以 i 位置为结尾的最小花费,当前位置的颜色只需要与前一个位置不同即可,在这个条件下求最小花费,i 位置可以有三个颜色,因此有三种状态需要考虑,他们都可能出现不同的结果,最终选择最小的那个。

class Solution {
public:
    int minCost(vector<vector<int>>& costs) {
        int m = costs.size();
        int n = costs[0].size();
        // dp[i] 表示刷到第 i 个房子时的最小花费
        // 但dp[i] 又可以继续细分为 多种状态  
        vector<vector<int>> dp(m + 1, vector<int>(n));
        for(int i = 1; i <= m; i++)
        {
            dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i - 1][0]; // i 位置为 红
            dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1]; // i 位置为 蓝
            dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2]; // i 位置为 绿
        }
        return min(dp[m][0], dp[m][1], dp[m][2]);
    }
};

复杂多状态问题

买卖股票的最佳时机含冷冻期

买卖股票的最佳时机含冷冻期

如果子状态比较多且相互影响难以分析,可以画状态转移图,必须搞清楚状态之间的关系!

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        // dp[i] 表示第 i 天时,你的最大利润
        // dp[i] 可以细分 为三种
//dp[i][0] 表示第 i 天结束时处于买入状态,dp[i][1] 第 i 天结束处于可交易状态,dp[i][2] 第 i 天结束处于冷冻期状态
        int m = prices.size();
        if(m == 1) return 0;
        vector<vector<int>> dp(m + 1, vector<int>(3));
        dp[0][0] -= prices[0];
        for(int i = 1; i <= m; i++)
        {
            // 如果子状态关系不好分析, 可以画状态转移表
            // 状态之间又关系且可能互相影响
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i - 1]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][2]);
            dp[i][2] = dp[i - 1][0] + prices[i - 1]; 
            cout << dp[i][0] << " " << dp[i][1] << " " << dp[i][2] << endl;
        }
        return max(dp[m][1], dp[m][2]);
    }
};

买卖股票的最佳时机含手续费

买卖股票的最佳时机含手续费

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        // dp[i] 表示第 i 天结束时,获得的最大利润
        int m = prices.size();
        vector<vector<int>> dp(m + 1, vector<int>(2, 0));
        // 0 代表第 i 天结束后,处于买入状态,1 代表卖出状态
        dp[0][0] -= prices[0];
        for(int i = 1; i <= m; i++)
        {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i - 1]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i - 1] - fee);
        } 
        return dp[m][1];
    }
};

买卖股票的最佳时机 Ⅲ 

买卖股票的最佳时机 III

用循环限制交易次数即可!

class Solution {
public:
    const int INF = 0x3f3f3f3f; // 初始化第一行, 为了后续求 max 的时候,不影响后续的结果!
    int maxProfit(vector<int>& prices) {
        int m = prices.size();
        // dp[i] 表示在第 i 天结束时获得的最大利润
        // dp[i] 可以分为好几个状态
        vector<vector<int>> f(m, vector<int>(3, -INF)); // 买入状态
        vector<vector<int>> g(m , vector<int>(3, -INF)); // 卖出状态
        f[0][0] = -prices[0], g[0][0] = 0;
        for(int i = 1; i < m; i++)
        {
            for(int j = 0; j < 3; j++)
            // j 表示参与交易的次数
            {
                f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]);
                g[i][j] = g[i - 1][j];
                if(j - 1 >= 0)  g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + prices[i]);
            }
        }
        int ret = 0;
        for(int j = 0; j < 3; j++) ret = max(ret, g[m - 1][j]);
        return ret;
   }
};

买卖股票的最佳时机 Ⅳ 

 买卖股票的最佳时机 IV

与限制次数为 2 次是相同的做法,用循环 k 次保证所有交易次数和状态能得到结果。

class Solution {
public:
    const int INF = 0x3f3f3f3f; // 初始化第一行, 为了后续求 max 的时候,不影响后续的结果!
    int maxProfit(int k, vector<int>& prices) {
        int m = prices.size();
        k = min(k, m / 2);
        // dp[i] 表示在第 i 天结束时获得的最大利润
        // dp[i] 可以分为好几个状态
        vector<vector<int>> f(m, vector<int>(k + 1, -INF)); // 买入状态
        vector<vector<int>> g(m , vector<int>(k + 1, -INF)); // 卖出状态
        f[0][0] = -prices[0], g[0][0] = 0;
        for(int i = 1; i < m; i++)
        {
            for(int j = 0; j <= k; j++) // 为什么要用 k 来循环,保证一共交易 j 次, 每次都有对应的最大利润
            {
                f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]);
                g[i][j] = g[i - 1][j];
                if(j - 1 >= 0)  g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + prices[i]);
            }
        }
        int ret = 0;
        for(int j = 0; j <= k; j++) ret = max(ret, g[m - 1][j]);
        return ret;
    }
};

子数组问题 

最大子数组和

最大子数组和

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        // dp[i]:以 i 位置为结尾的数组的最大子数组和
        int n = nums.size();
        vector<int> dp(n + 1);
        dp[0] = 0;
        for(int i = 1; i <= n; i++)
        {
            dp[i] = max(nums[i - 1], dp[i - 1] + nums[i - 1]);
        }
        // 不一定以 n - 1 位置为结尾时,子数组的和最大
        int ret = dp[1];
        for(int i = 1; i <= n; i++) if(dp[i] > ret) ret = dp[i];
        return ret;
    }
};

环形子数组的最大和 

 环形子数组的最大和

将结果分为两种,一种是不包含头尾的状态,一种是包含头尾的状态,包含头尾就需要使用正难则反的思想,将问题变为数组内进行操作! 

class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        const int INF = 0x3f3f3f3f;
        int n = nums.size();
        // 环形 dp 问题, 转化为非环形
        // 1. 目标子数组未连接头尾,直接求最大连续子数组的和
        // 2. 目标子数组连接头尾,最大连续子数组的和 转化为用整个数组的和 sum 减去 最小连续子数组的和! 
        // dp[i] 表示以 i 位置为结尾的子数组和的最大值, sp[i] 表示以 i 位置为结尾的子数组和的最小值
        vector<int> dp(n + 1);
        auto sp = dp; // 和的最小值
        dp[0] = -INF, sp[0] = INF;
        int sum = 0;
        for(int i = 1; i <= n; i++)
        {
            dp[i] = max(dp[i - 1] + nums[i - 1], nums[i - 1]);
            sp[i] = min(sp[i - 1] + nums[i - 1], nums[i - 1]);
            sum += nums[i - 1];
        }
        int max_dp = dp[1];
        int min_sp = sp[1];
        for(int i = 1; i <= n; i++)
        {
            if(dp[i] > max_dp) max_dp = dp[i];
            if(sp[i] < min_sp) min_sp = sp[i];
        }
        // 当数组全部为负数的时候, sum 等于 sp[i],这种情况直接返回 max_dp
        return dp[i] == sum ? max_dp : max(max_dp, sum - min_sp);
    }
};

乘积最大数组

乘积最大子数组

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int n = nums.size();
        // 因为两个负数乘起来是一个正数,因此不能直接用 nums[i] * dp[i - 1] 
        // 因此, 当 nums[i] 等于一个负数的时候, 需要乘一个最小乘积,才能得到最大的数
        // 所以, 还需要一个数组来记录前乘积最小的数组
        vector<int> f(n + 1);
        auto g = f;
        f[0] = 1, g[0] = 1;
        for(int i = 1; i <= n; i++)
        {
            // 需要判断 nums[i] 的正负
            if(nums[i - 1] > 0) 
            {
                f[i] = max(f[i - 1] * nums[i - 1], nums[i - 1]);
                g[i] = min(g[i - 1] * nums[i - 1], nums[i - 1]);
            }
            else
            {
                f[i] = max(g[i - 1] * nums[i  -1], nums[i - 1]);
                g[i] = min(f[i - 1] * nums[i - 1], nums[i - 1]);
            }
        }
        int ret = f[1];
        for(int i = 1; i <= n; i++) if(f[i] > ret) ret = f[i];
        return ret;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Numpy】练习题100道(1-25题)

#学习笔记# 在学习神经网络的过程中发现对numpy的操作不是非常熟悉&#xff0c;遂找到了Numpy 100题。 Git-hub链接 目录 1 题目列表&#xff1a; 2 题解&#xff1a; 1 题目列表&#xff1a; 导入numpy包&#xff0c;并将其命名为np&#xff08;★☆☆&#xff09; 打印…

设计模式学习笔记 - 规范与重构 - 5.如何通过封装、抽象、模块化、中间层解耦代码?

前言 《规范与重构 - 1.什么情况下要重构&#xff1f;重构什么&#xff1f;又该如何重构&#xff1f;》讲过&#xff0c;重构可以分为大规模高层重构&#xff08;简称 “大型重构”&#xff09;和小规模低层次重构&#xff08;简称 “小型重构”&#xff09;。大型重构是对系统…

3.6研究代码(2)

指的是微电网运行参数。 在MATLAB中&#xff0c;randi([0,1],1,48) 会生成一个包含1*48个0或1的随机整数数组。这意味着数组中的每个元素都将是0或1。 MATLAB帮助中心&#xff1a;均匀分布的伪随机整数 - MATLAB randi - MathWorks 中国https://ww2.mathworks.cn/help/matlab/r…

Java零基础入门到精通_Day 1

01 Java 语言发展史 Java语言是美国Sun公司(StanfordUniversity Network)在1995年推出的 计算机语言Java之父:詹姆斯高斯林(ames Gosling) 重要的版本过度&#xff1a; 2004年 Java 5.0 2014年 Java 8.0 2018年 9月 Java 11.0 &#xff08;目前所使用的&#xff09; 02 J…

llama factory学习笔记

模型 模型名模型大小默认模块TemplateBaichuan27B/13BW_packbaichuan2BLOOM560M/1.1B/1.7B/3B/7.1B/176Bquery_key_value-BLOOMZ560M/1.1B/1.7B/3B/7.1B/176Bquery_key_value-ChatGLM36Bquery_key_valuechatglm3DeepSeek (MoE)7B/16B/67Bq_proj,v_projdeepseekFalcon7B/40B/18…

#LT8711V适用于Type-C/DP1.2/EDP转VGA应用方案,分辨率高达1080P。

1. 概述 LT8711V是一款高性能 Type-C/DP1.2 转 VGA 转换器&#xff0c;设计用于将 USB Type-C 源或 DP1.2 源连接到 VGA 接收器。 该LT8711V集成了一个符合DP1.2标准的接收器和一个高速三通道视频DAC。此外&#xff0c;还包括两个用于 CC 通信的 CC 控制器&#xff0c;以实现 …

文件服务器

文件服务器 # 构建NFS远程共享存储## 一、NFS介绍shell 文件系统级别共享&#xff08;是NAS存储&#xff09; --------- 已经做好了格式化&#xff0c;可以直接用。 速度慢比如&#xff1a;nfs&#xff0c;sambaNFS NFS&#xff1a;Network File System 网络文件系统&#xf…

C++面向对象..

1.面向对象的常见知识点 类、 对象、 成员变量(属性)、成员函数(方法)、 封装、继承、多态 2.类 在C中可以通过struct、class定义一个类 struct和class的区别&#xff1a; struct的默认权限是public(在C语言中struct内部是不可以定义函数的) 而class的默认权限是private(该权…

Windows虚拟机的安装

Windows系统 总结知识点记忆级别&#xff1a; 1级&#xff1a;熟练记忆讲过的所有知识点(按照授课顺序&#xff0c;笔记顺序来提问)2级&#xff1a;灵活应用所学知识点(不按照顺序提问&#xff0c;面临陷阱提问)3级&#xff1a;应用所学知识解决实际问题4级&#xff1a;扩展应…

24 深度卷积神经网络 AlexNet【李沐动手学深度学习v2课程笔记】(备注:含AlexNet和LeNet对比)

目录 1. 深度学习机器学习的发展 1.1 核方法 1.2 几何学 1.3 特征工程 opencv 1.4 Hardware 2. AlexNet 3. 代码 1. 深度学习机器学习的发展 1.1 核方法 2001 Learning with Kernels 核方法 &#xff08;机器学习&#xff09; 特征提取、选择核函数来计算相似性、凸优…

陈景东:集中与分布式拾音与声信号处理 | 演讲嘉宾公布

一、声音与音乐技术专题论坛 声音与音乐技术专题论坛将于3月28日同期举办&#xff01; 声音的应用领域广泛而深远&#xff0c;从场所识别到乐器音响质量评估&#xff0c;从机械故障检测到心肺疾病诊断&#xff0c;声音都发挥着重要作用。在互联网、大数据、人工智能的时代浪潮中…

【python】random库函数使用简要整理

前言 简要快速清晰整理random库 函数 函数作用random()返回0-1间的浮点小数randint(1,10)返回1到10间的整数uniform(1,10)返回1-10间的小数randrange(1,10,2)从1每隔2取一个数到10&#xff0c;在这些数中返回一个choice(列表)从列表中随机返回一个 shuffle(列表) 对列表内容…

高等数学常用公式

高等数学常用公式 文章目录 内容大纲 内容 大纲 感谢观看 期待关注 有问题的小伙伴请在下方留言&#xff0c;喜欢就点个赞吧

群晖NAS使用Docker安装WPS Office并结合内网穿透实现公网远程办公

文章目录 推荐1. 拉取WPS Office镜像2. 运行WPS Office镜像容器3. 本地访问WPS Office4. 群晖安装Cpolar5. 配置WPS Office远程地址6. 远程访问WPS Office小结 7. 固定公网地址 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff…

C语言中的UTF-8编码转换处理

C语言UTF-8编码的转换 1.C语言简介2.什么是UTF-8编码&#xff1f;2.1 UTF-8编码特点&#xff1a; 3.C语言中的UTF-8编码转换处理步骤1&#xff1a;获取UTF-8编码的字节流步骤2&#xff1a;解析UTF-8编码步骤3&#xff1a;Unicode码点转换为汉字 4.总结 1.C语言简介 C语言是一门…

怎么做加密文件二维码?分享文件更安全

怎么做一个加密文件二维码&#xff1f;在日常的工作和生活中&#xff0c;通过扫描二维码来查看或者下载文件的方式&#xff0c;被越来越多的人所使用&#xff0c;一方面是二维码的成本低&#xff0c;另一方面有利于提升便捷性和用户体验。 为了保证内容的隐私性和安全性&#…

数据库期末速成100分训练,附练手数据库原件及教程

本文提供下面数据库代码的数据库原件&#xff0c;下载后可使用 教程如下&#xff1a; 1.打开sql sever 2.找到数据库 3.右键数据库点击“附加”&#xff0c;然后点击“添加” 4.导入数据库原件&#xff0c;点击确定 ps&#xff1a;如果没有sqlsever 或者页面编辑器&#x…

uniapp引入jQuery

安装 npm install jquery --saveoryarn add jquery引入 import Vue from vue import jquery from "jquery"; Vue.prototype.$ jquery;<template><view>abc</view> </template><script>export default {data() {return {}}} </scr…

tcp服务器客户端通信(socket编程)

目录 1.编程流程 2.代码演示 2.1 服务器代码 2.2 客户端代码 3.注意 3.1 ping命令 3.2 netstat命令 3.3 为什么memset? 3.4 哪个会阻塞? 3.5 显示连接信息 1.概念 1.1 编程流程 1.2 connect与listen connect方法执行后&#xff0c;会进行三次握手&#xff0c;建立连…

【python 】----Pytest基础知识与进阶知识

定义 用于编写和执行Python测试全功能测试框架(工具),是一个第三方库 安装 pip insatll pytest 安装pytest --version 校验 pytest的组成构成 不写调用语句也可以执行函数内容 在用例运行语句里面: -s:指的是开启与终端的交互,如果没有-s(程序不会输入与打印),一条用…