二刷 动态规划

什么是动态规划 Dynamic Programming DP

如果某一问题有很多重叠子问题,使用动态规划时最有效的

动态规划中每一个状态是由上一个状态推导出来的。

动规五部曲

1.确定dp数组以及下标的含义

2.确定递归公式

3.dp数组如何初始化

4.确定遍历顺序

5.举例推导dp数组


509.斐波那契数

1.确定dp数组和下标的含义

dp[i]:第i个数的斐波那契数值是dp[i]

2.确定递推公式

dp[i] = dp[i-1]+dp-i-2

3.dp数组如何初始化

dp[0] = 0;

dp[1]=  1

4.确定遍历顺序

dp[i]依赖dp[i-1],dp[i-2],因此是从前向后

5.举例推导

0 1 1 2 3 5 8 13

class Solution {
public:
    int fib(int n) {
        //如果是0,1,直接返回
        if(n <= 1) return n;
        //创建dp数组
        vector<int> dp(n+1);
        //初始化
        dp[0] = 0;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];

    }
};

70.爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

  • 输入: 2
  • 输出: 2
  • 解释: 有两种方法可以爬到楼顶。
    • 1 阶 + 1 阶
    • 2 阶

1.确定dp数组及下标含义

dp[i]:爬上i楼有dp[i]种方法

2.确定递推公式

第一层有一种方法

第二层有两种方法

第一层跨两步到第三层;第二层跨一步到第三层;

所以第三层楼梯的状态可以由第二层楼梯和到第一层楼梯的状态推导出来

dp[i-1],上i-1层楼梯,有dp[i-1]种方法,再一步跳一个台阶到dp[i]

dp[i-2],上i-2层楼梯,有dp[i-2]种方法,再一步跳两个台阶就是dp[i]。

dp = dp[i-1]+dp[i-2]

3.dp数组初始化

dp[1] = 1

dp[2] = 2

4.确定遍历顺序

从前向后

5.模拟

class Solution {
public:
    int climbStairs(int n) {
        if ( n <= 1) return n;
        vector<int> dp(n+1);
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
};

746. 使用最小花费爬楼梯

给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

请你计算并返回达到楼梯顶部的最低花费。

1.确定dp数组和下标含义

dp[i]:到达i楼层的最低花费是dp[i]

2.确定递推公式

dp[i] = dp[i-1] + cost[i -1]

dp[i] = dp[i-2] + cost[i -2]

dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);

3.初始化

到达第0和第1台阶不需要花费体力

dp[0] = 0;

dp[1] = 0;

4.遍历顺序

从前向后

5.模拟

此处的n是cost.size()

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        vector<int> dp(cost.size() + 1);
        dp[0] = 0;
        dp[1] = 0;
        for (int i = 2; i <= cost.size(); i++) {
            dp[i] = min (dp[i-1] + cost[i - 1], dp[i-2] + cost[i - 2]);
        }
        return dp[cost.size()];
    }
};

62.不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

机器人从00出发到m-1,n-1

1.确定dp数组和下标含义

dp[i][j]:从00出发到ij有dp[i][j]条不同的路径

2.确定递推公式

只有两个方向能来

dp[i][j] = dp[i-1][j] + dp[i][j-1];

3.初始化

for  dp[i][0] = 1

for  dp[0][j] = 1

4.遍历顺序

从左到右一层一层遍历

注意最后一个点是m-1,n-1

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for(int i = 0; i < m; i++) dp[i][0] = 1;
        for(int j = 0; j < n; j++) dp[0][j] = 1;
        //双层循环
        for(int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++){
                dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
            }
        }
        return dp[m - 1][n - 1];
    }
};

63. 不同路径 II

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

思路:

1.确定dp数组和下标含义

dp[i][j]:从00到m-1,n-1有dp[i-1][j-1]条路径

2.确定递推公式

没有障碍情况下

if(obstacleGrid[i][j] == 0)

dp[i][j] = dp[i-1][j] + dp[i][j-1]

3.确定初始化

没有障碍才能为1

4.左上到右下

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        //起点或终点有障碍物,直接返回0;
        if (obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1) return 0;
        vector<vector<int>> dp(m, vector<int>(n, 0));
        // 初始化,没有障碍物才能为1,遇到障碍物就为0
        for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
        for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1; 
        //遍历,遇到障碍物就跳过
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] == 1) continue;
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
};

343. 整数拆分

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

示例 1:

  • 输入: 2
  • 输出: 1
  • 解释: 2 = 1 + 1, 1 × 1 = 1。

1.确定dp数组和下标的含义

dp[i]:正整数i划分后得到的最大乘积

2.确定递推公式

从1遍历j,

将i划分为两个数 :dp = j*(i-j)

继续划分:j*dp[i-j]

dp[i] = max({dp[i], j*(i-j),j*dp[i-j]})

3.初始化

dp[2] = 1

4.递归顺序

从前向后

class Solution {
public:
    int integerBreak(int n) {
        vector<int> dp(n + 1);
        dp[2] = 1;
        for (int i = 3; i <= n; i++) {
            //i/2:一般乘积最大 是中间的数
            for (int j = 1; j <= i/2; j++) {
                //j * (i-j)表示分成两个数字;j*dp[i - j]表示分成两个以上数字
                dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]));
            }
        }
        return dp[n];
    }
};

96.不同的二叉搜索树

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

1.确定dp[i]数组及下标的含义

dp[i]:以1-i为节点组成的二叉搜索树由dp[i]种

2.确定递推公式

n=3时

元素1为头节点搜索树的数量 = 右子树有2个元素的搜索树数量*左子树有0个元素的搜索树数量

元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量*左子树有1个元素的搜索树数量

元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量*左子树有2个元素的搜索树数量

有两个元素的搜索树数量是dp[2]

有1个元素的搜索树数量是dp[1]

有0个元素的搜索树数量是dp[0]

dp[3] = dp[2]*dp[0] + dp[1]*dp[1]+dp[0]*dp[2]

dp[i] += dp[以j为头结点左子树节点数量]*dp[以j为头结点右子树节点数量]

j相当于头节点的元素,从1遍历到i为止

递推公式:dp[i] += dp[j - 1]*dp[i-j]

3.初始化

dp[0] = 1;

4.遍历顺序

i是依靠i之前的节点数的状态

for(int i = 1; i<=n; i++) {

        for (int j = 1;j <= i;j++) {

                dp[i] += dp[j - 1]* dp[i-j] }

}

5.模拟

class Solution {
public:
    int numTrees(int n) {
        vector<int> dp(n + 1);
        dp[0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }
        return dp[n];
    }
};

198.打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

  • 示例 1:
  • 输入:[1,2,3,1]
  • 输出:4

1.确定dp[i]数组及下标的含义

dp[i]:考虑下标i以内的房屋,偷窃的最高金额

2.确定递推公式

如果偷第i间房,找出i-2以内的房屋最多可偷的金额+这间房的金额:dp[i] = dp[i - 2] + nums[i]

如果不偷第i间房,则可以考虑第i-1间房,但不一定就要偷i-1:dp[i] = dp[i-1]

dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);

3.初始化

dp[0] = nums[0];

dp[1] = max(nums[0], nums[0]);

4.遍历顺序

从前往后

  

注意要当nums只有一个时,直接返回这个即可。

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 1) return nums[0];
        vector<int> dp(nums.size());
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        for (int i = 2; i < nums.size(); i++) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[nums.size() - 1];
    }
};

213.打家劫舍II

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。

示例 1:

  • 输入:nums = [2,3,2]

  • 输出:3

1.确定dp数组和下标的含义

dp[i]:i房屋以内的房屋最大的偷窃金额是dp[i]

2.确定递推公式

考虑两种情况:只包含头和只包含尾分别考虑,取最大值

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 1) return nums[0];
        int result1 = robRange(nums, 0, nums.size() - 2);
        int result2 = robRange(nums, 1, nums.size() - 1);
        return max (result1, result2);
    }

    int robRange(vector<int>& nums, int start, int end) {
    vector<int> dp(nums.size());
    dp[start] = nums[start];
    dp[start + 1] = max(nums[start], nums[start + 1]);
    for (int i = start + 2; i <= end; i++) {
        dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
    }
    return dp[end];
}
};

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

  • 示例 1:

  • 输入:[7,1,5,3,6,4]

  • 输出:5

1.确定dp[i]及下标的含义

dp[i][0]:第i天不持有股票

dp[i][1]:第i天持有股票

2.递推公式

dp[i][0]:第i天不持有股票有两种情况

第i-1天就不持有:dp[i - 1][0]

第i-1天持有,第i天卖出:dp[i - 1][1] + prices[i]

求最大值

dp[i][1]:第i天持有股票有两种情况

第i-1天就持有:dp[i - 1][1]

第i-1天不持有,第i天买入:- prices[i]

---这里 只买一次,第一次买股票 手头现金一定是0,所以直接-prices[i]

求最大值

3.初始化

dp[0][0] = 0

dp[0][1] = -prices[0]

4.遍历顺序

5.模拟

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (prices.size() == 0) return 0;
        vector<vector<int>> dp(prices.size(),vector<int>(2));
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < prices.size(); i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = max(-prices[i], dp[i - 1][1]);
        }
    //最后一定是选择不持有股票赚的多
        return dp[prices.size() - 1][0];
    }
};

122.买卖股票的最佳时机II

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

  • 示例 1:

  • 输入: [7,1,5,3,6,4]

  • 输出: 7

1.确定dp[i]数组及下标的含义

dp[i][0]:不持有股票

dp[i][1]:持有股票

2.确定递推公式

dp[i][0]:第i天不持有股票

第i-1天就不持有,dp[i-1][0]

第i-1天持有,第i天卖出:dp[i - 1][1] + prices[i]

dp[i][1]:第i天持有股票

第i-1天就持有:dp[i-1][1]

第i-1天不持有,第i天买入:dp[i - 1][0] -prices[i]

唯一不同点:买卖多次股票,买入的时候手头现金非0

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        vector<vector<int>> dp(len, vector<int>(2, 0));
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < len; i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
        }
        return dp[len - 1][0];
    }
};

647. 回文子串

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例 1:

  • 输入:"abc"
  • 输出:3
  • 解释:三个回文子串: "a", "b", "c"

1.确定dp[i]及下标的含义

dp[i][j]:[i,j]区间内是否是回文串

2.递推公式

s[i]==s[j]分为三种情况

a, aa都属于i-j<=1,相差一个距离

相差多个距离ababa,要根据dp[i+1][j-1]是否满足回文串了

3.初始化

初始都为false

4.遍历顺序

因为dp[i][j]依赖于dp[i+1][j-1] 所以从下往上从左往右

class Solution {
public:
    int countSubstrings(string s) {
        int len = s.size();
        int result = 0;
        vector<vector<bool>> dp(len, vector<bool>(len, false));
        for (int i = len - 1; i >= 0; i--) {
            for (int j = i; j < len; j++) {//j从i开始
                if (s[i] == s[j]) {
                    if (j - i <= 1) {
                        result++;
                        dp[i][j] = true;
                    } else if (dp[i + 1][j - 1]) {
                        result++;
                        dp[i][j] = true; 
                    }
                }
            }
        }
        return  result;
    }
};

516.最长回文子序列

给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000 。

示例 1: 输入: "bbbab" 输出: 4 一个可能的最长回文子序列为 "bbbb"。

示例 2: 输入:"cbbd" 输出: 2 一个可能的最长回文子序列为 "bb"。

回文子序列不连续

1.确定dp[i]数组和下标

dp[i][j]:字符串s在[i,j]范围里最长的回文子序列的长度是dp[i][j]

2.确定递推公式

如果s[i] == s[j] ,dp[i][j] = dp[i+1][j-1]+2

如果s[i] != s[j], dp[i][j] = max(dp[i+1][j], dp[i][j-1]);看看分别加入s[i]、s[j]哪一个可以组成最长的回文子序列。

3.初始化

i=j相同的时候,初始化为1

其他默认为0

4.遍历顺序

dp[i][j]依赖于dp[i+1][j-1],从下往上,从左往右

内层循环:for(j = i+1)原因是,j必须大于i,并且j=i已经初始化了

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));
        //i=j的时候,为1
        for(int i = 0; i < s.size(); i++) dp[i][i] =1;
        for(int i = s.size() - 1; i >= 0; i--) {
            for (int j = i + 1; j < s.size(); j++) {
                if (s[i] == s[j]) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;
                }else if (s[i] != s[j]) {
                    dp[i][j] = max(dp[i+1][j], dp[i][j-1]);
                }
            }
        }
        return dp[0][s.size() - 1];
    }
};

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

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

相关文章

分班查询系统,老师们应该如何制作?

新学期的开始&#xff0c;作为教师&#xff0c;我们面临的一项关键任务就是组织分班。传统分班方法往往需要处理大量的数据&#xff0c;这个过程不仅耗时&#xff0c;而且容易出错。为了简化这一流程&#xff0c;提高效率&#xff0c;我们可以利用现代技术&#xff0c;创建一个…

VSCode打开其它IDE项目注释显示乱码的解决方法

问题描述&#xff1a;VSCode打开Visual Studio&#xff08;或其它IDE&#xff09;工程&#xff0c;注释乱码&#xff0c;如下图所示&#xff1a; 解决方法&#xff1a;点击VSCode右下角的UTF-8&#xff0c;根据提示点击“通过编码重新打开”&#xff0c;再选择GB2312&#xff0…

【触想智能】工业平板电脑在新能源领域上的应用分析

工业平板电脑是一种具有高性能和稳定性的计算机设备&#xff0c;适用于在恶劣环境下进行数据采集、运营管理和现场操作。 随着新能源技术的快速发展&#xff0c;工业平板电脑不断地得到应用&#xff0c;并且已成为新能源领域中的重要工具之一。本文将从四个方面探讨工业平板电脑…

VMware Mac/Win 虚拟机软件介绍

VMware作为全球领先的虚拟化技术提供商&#xff0c;其Mac/Win虚拟机软件为用户带来了前所未有的跨平台操作体验。这款软件凭借其强大的功能和稳定的性能&#xff0c;成为了众多开发者、设计师、企业用户以及个人用户的首选工具。 强大的多操作系统支持 VMware Mac/Win 虚拟机…

c++习题06-ljc的储蓄计划

目录 一&#xff0c;问题 二&#xff0c;思路 1&#xff0c;思路1 2&#xff0c;思路2 三&#xff0c;代码 1&#xff0c;思路1代码 2&#xff0c;思路2代码 四&#xff0c;用例输入输出 一&#xff0c;问题 二&#xff0c;思路 1&#xff0c;思路1 定义变量&#x…

频繁调价不用愁,统一销售报价话术就用聊天宝

前言 在当今的数字化时代&#xff0c;企业面临着日益增长的客户服务需求&#xff0c;特别是在电商、销售等领域。客服团队的效率和响应速度直接影响到客户满意度和企业的专业形象。面对频繁变动的价格信息和销售策略&#xff0c;如何确保客服回复的及时性和准确性成为了一大挑…

uboot 编译时传递参数实现条件编译

KCFLAGS make ARCHarm KCFLAGS-DENV_DEBUG CROSS_COMPILEaarch64-linux-gnu-env/sf.c env_sf_save 加入调试信息 # saveenv Saving Environment to SPI Flash... env_sf_save (1) spi_flash_erase (2) spi_flash_write is40000 Erasing SPI flash...Writing to SPI flash.…

Git入门 本地仓库 远端仓库 多分支

Git入门 Git入门本地git初始化git仓库初始化 创建远端仓库githubgitee 指定远端仓库推送至远端多分支将feature分支合并至dev分支 其他开发者 Git入门 本地git初始化 git仓库初始化 mkdir myrepo # 创建仓库文件夹 cd myrepo/ # 进入目录 git init # 初始化git仓库 (创建.g…

YOLOv8改进 | 卷积模块 | 减少冗余计算和内存访问的PConv【CVPR2023】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效…

某Dota/IM对战平台玩家助手、查看战绩下、胜率等

功能说明 WAR3游戏启动后&#xff0c;可以自动获取游戏双方的玩家列表&#xff0c;然后查询显示玩家的战绩及个人信息。附带查看玩家的战绩详情、最近游戏&#xff0c;查看对手及友方的战绩详情&#xff0c;据此推算出是否开黑、是否小号等信息 使用方法及运行效果 启动 查…

品牌推广怎么样?掌握正确做法,让品牌大放异彩!

品牌推广对于初创公司来说是一项至关重要的任务。在市场众多品牌中&#xff0c;如何脱颖而出&#xff0c;是每个品牌方都要考虑的问题。 作为一名手工酸奶品牌的创始人&#xff0c;目前全国复制了100多家门店&#xff0c;我来分享下&#xff0c;如何推广&#xff0c;可以让品牌…

前端基础--Vue3

Vue3基础 VUE3和VUE2的区别 2020年9月18日&#xff0c;Vue.js发布版3.0版本&#xff0c;代号&#xff1a;One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。体积更小 Vue3.0 打包大小减少41%。 同时Vue3可以更好的支持T…

Python爬虫与数据可视化:构建完整的数据采集与分析流程

Python爬虫技术概述 Python爬虫是一种自动化的数据采集工具&#xff0c;它可以模拟浏览器行为&#xff0c;访问网页并提取所需信息。Python爬虫的实现通常涉及以下几个步骤&#xff1a; 发送网页请求&#xff1a;使用requests库向目标网站发送HTTP请求。获取网页内容&#xf…

多模态大模型面对误导性问题:看懂图片也会答错,一骗就中招

多模态大语言模型&#xff08;MLLMs&#xff09;因其在视觉理解和推理方面的突出表现&#xff0c;例如生成详细的图像描述和回答复杂的问题等&#xff0c;逐渐成为近期AI研究的热点。 然而&#xff0c;Bunny 团队的最新研究发现&#xff0c;尽管许多MLLMs对视觉内容能够正确理…

MM-LLM:使用Llava类构建图文多模态大模型实践

多模态大模型的结构如上&#xff0c;llava是用两层MLP作为连接器。该模式也是后续很多工作的基础。 本文主要参考了https://github.com/yuanzhoulvpi2017/zero_nlp/tree/main/train_llava的工作&#xff0c;最初是在b站看到的&#xff0c;讲解的很细致。 基础模型 大语言模型…

夏日编码狂欢:GitCode x DevUI挑战赛,点燃你的创造力

在这个创新驱动的时代&#xff0c;开源技术已成为推动全球软件开发进步的强大引擎&#xff0c;技术的边界正被全球开发者的集体智慧不断拓展。 在这个充满活力的夏日&#xff0c;开源社区迎来了一场全新的活动——由GitCode携手华为云DevUI精心打造的开源共创挑战赛。这不仅是…

【瑞吉外卖 | day01】项目介绍+后台登录退出功能

文章目录 瑞吉外卖 — day011. 所需知识2. 软件开发整体介绍2.1 软件开发流程2.2 角色分工2.3 软件环境 3. 瑞吉外卖项目介绍3.1 项目介绍3.2 产品原型展示3.3 技术选型3.4 功能架构3.5 角色 4. 开发环境搭建4.1 数据库环境搭建4.2 Maven项目构建 5. 后台系统登录功能5.1 创建需…

The Sandbox 通过创作者挑战推动社区参与

游戏开发者并不是每天都有机会让自己的作品赢得大奖。但在 The Sandbox&#xff0c;这已经成为一种趋势&#xff01;首届 "创作者挑战 "让顶尖创作者将 150 万 SAND 捧回家。现在&#xff0c;我们要带着另一个巨额奖池回来了&#xff01; 关于首届创作者挑战&#xf…

代理IP的10大误区:区分事实与虚构

在当今的数字时代&#xff0c;代理已成为在线环境不可或缺的一部分。它们的用途广泛&#xff0c;从增强在线隐私到绕过地理限制。然而&#xff0c;尽管代理无处不在&#xff0c;但仍存在许多围绕代理的误解。在本博客中&#xff0c;我们将探讨和消除一些最常见的代理误解&#…

昇思25天学习打卡营第7天|函数式自动微分

函数式自动微分 概念函数与计算图微分函数与梯度计算自定义神经网络梯度计算参考 概念 神经网络的训练主要使用反向传播算法&#xff0c;模型预测值&#xff08;logits&#xff09;与正确标签&#xff08;label&#xff09;送入损失函数&#xff08;loss function&#xff09;…