代码随想录-笔记-其八

news2024/12/27 16:38:33

让我们开始:动态规划!

70. 爬楼梯 - 力扣(LeetCode)

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

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

class Solution {
public:
    int climbStairs(int n) {
        vector<int> dp(n+1);
        if(n==0)return 0;
        if(n==1)return 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];
    }
};

动态规划是客观地说最注重逻辑的题型,因为我们必须要找到由子问题推导到主问题的这个过程才可以做。爬楼梯的这个逻辑是什么呢?当我们i来到3以后,我们就可以把爬三阶楼梯拆分成爬一个二阶(三减一)的楼梯方法加一次爬一阶和爬一个一阶(三减二)的楼梯加一次爬两阶,同理四阶就是一个爬一个三阶的楼梯方法加一次一步和爬二阶的楼梯方法加一次两步。

746. 使用最小花费爬楼梯 - 力扣(LeetCode)

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

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

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

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

这个题的递推的关键在于找到最小花费,我们需要考量爬到i阶楼梯的最小花费,由于每次只能爬一阶或者二阶,所以我们只需要往前找一阶的最小花费加上该阶的花费与往前两阶的最小花费与该阶的花费即可。

62. 不同路径 - 力扣(LeetCode)

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

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

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

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

二维动态规划的例题,这里的dp[i][j]代表的意思是i*j的网格到终点的路径数,如果是一行或者一列的话都是1,然后第i行j列等同于从i-1行j列的路径数与i行j-1列的路径数的总和。

63. 不同路径 II - 力扣(LeetCode)

给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角(即 grid[0][0])。机器人尝试移动到 右下角(即 grid[m - 1][n - 1])。机器人每次只能向下或者向右移动一步。

网格中的障碍物和空位置分别用 1 和 0 来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。

返回机器人能够到达右下角的不同路径数量。

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

这个题无疑要麻烦得多,因为障碍物的出现,我们必须随时检查障碍物是否存在。除此之外和正常的不同路径区别不大,注意边界条件的处理以及网格的下标与我们动态数组的下标的对应关系。

343. 整数拆分 - 力扣(LeetCode)

给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。

返回 你可以获得的最大乘积 。

class Solution {
public:
    int integerBreak(int n) {
        vector<int> dp(n+1);
        dp[2]=1;
        for(int i=3;i<=n;++i){
            for(int j=1;j<=i/2;++j){
                dp[i]=max(dp[i],max(dp[i-j]*j,(i-j)*j));
            }
        }
        return dp[n];
    }
};

这个题虽然结果看起来似乎非常简单,但其中涉及到的思路其实挺复杂。这里dp[i]主要考虑了三种情况:dp[i]本身,dp[i-j]*j(整数i-j的最大乘积乘以j),(i-j)*j(整数i-j乘以j),来考虑整数i的最大乘积,j利用了乘法的性质可以少遍历一半的区间。

96. 不同的二叉搜索树 - 力扣(LeetCode)

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

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

这里我就不用自己的话赘述了。直接上图吧

本质上是一个找规律并表达出来的问题。

46. 携带研究材料(第六期模拟笔试) (kamacoder.com)

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。 

小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。

#include <iostream>
#include <vector>
using namespace std;
int main(){
    int n,zooms;
    cin>>n>>zooms;
    vector<int> weights(n);
    vector<int> values(n);
    for(int i=0;i<n;++i){
        cin>>weights[i];
    }
    for(int i=0;i<n;++i){
        cin>>values[i];
    }
    vector<vector<int>> dp(n+1,vector<int>(zooms+1,0));
    for(int j=weights[0];j<=zooms;++j){
        dp[0][j]=values[0];
    }
    for(int i=1;i<n;++i){
        for(int j=0;j<=zooms;++j){
            if(j<weights[i])dp[i][j]=dp[i-1][j];
            else dp[i][j]=max(dp[i-1][j],dp[i-1][j-weights[i]]+values[i]);
        }
    }
    cout<<dp[n-1][zooms]<<endl;
    return 0;
}

0-1背包作为动态规划的经典题目,可以说非常重要,难点其实主要在于对dp数组的理解以及初始化的过程,要做到每一步在干嘛心中有数才可以。

#include <iostream>
#include <vector>
using namespace std;
int main(){
    int n,zooms;
    cin>>n>>zooms;
    vector<int> weights(n);
    vector<int> values(n);
    for(int i=0;i<n;++i){
        cin>>weights[i];
    }
    for(int i=0;i<n;++i){
        cin>>values[i];
    }
    vector<int> dp(zooms+1,0);
    for(int i=0;i<n;++i){
        for(int j=zooms;j>=weights[i];--j){
            dp[j]=max(dp[j],dp[j-weights[i]]+values[i]);
        }
    }
    cout<<dp[zooms]<<endl;
    return 0;
}

在这里放上第二种做法:将二维数组dp转换为一维数组,从背包空间容量大小开始从上往下遍历,分别得到最大的价值。值得一提的是一维的动态规划数组一定不能正向遍历,因为这会反复调用已经被确认的dp数组里的值,变成完全背包问题。

416. 分割等和子集 - 力扣(LeetCode)

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=accumulate(nums.begin(), nums.end(), 0);
        if(sum%2!=0)return false;
        int target=sum/2;
        vector<int> dp(target+1);
        for(int i=0;i<nums.size();++i){
            for(int j=target;j>=nums[i];--j){
                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[target]==target;
    }
};

这是一个典型的0-1背包应用题,我们要判断能否分割成两个和相等的子集,其实就是判断我们能否填满容量为数组总和一半的背包,就变成了我们的0-1背包问题,这里我们的物体的容量和价值相同,都是nums[i]。

1049. 最后一块石头的重量 II - 力扣(LeetCode)

有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。

每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x

最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int n=stones.size();
        vector<int> dp(15001,0);
        int sum=accumulate(stones.begin(), stones.end(), 0);
        int target=sum/2;
        for(int i=0;i<n;++i){
            for(int j=target;j>=stones[i];--j){
                dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);
            }
        }
        return sum-dp[target]-dp[target];
    }
};

这个题其实和上个题类似,也是找能否填满容量为数组总和的一半的背包问题,不过这个题不用返回是否,而是返回最小的差值,具体来说,只是return 的东西不太一样。

494. 目标和 - 力扣(LeetCode)

给你一个非负整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

  • 例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=accumulate(nums.begin(), nums.end(), 0);
        if((target+sum)%2!=0)return 0;
        int left=(target+sum)/2;
        vector<int> dp(left+1,0);
        dp[0]=1;
        for(int i=0;i<nums.size();++i){
            for(int j=left;j>=nums[i];--j){
                dp[j]+=dp[j-nums[i]];
            }
        }
        return dp[left];
    }
};

这个题其实比想象中还要难理解,对于这个题而言,可能真正的难点在于如何将问题转换为背包问题,我将视频链接放在这里。
动态规划之背包问题,装满背包有多少种方法?| LeetCode:494.目标和_哔哩哔哩_bilibili

474. 一和零 - 力扣(LeetCode)

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        for(string str:strs){
            int oneNum=0,zeroNum=0;
            for(char c:str){
                if(c=='0')zeroNum++;
                else oneNum++;
            }
            for(int i=m;i>=zeroNum;--i){
                for(int j=n;j>=oneNum;--j){
                    dp[i][j]=max(dp[i][j],dp[i-zeroNum][j-oneNum]+1);
                }
            }
        }
        return dp[m][n];
    }
};

这个题其实是一个比较经典的0-1背包问题,只是将物品的序号由一个一维的数组变成了一个二维的数组,这就比较考察我们对0-1背包的基本理解了。这题比较容易犯错的地方在于最后的递推公式中的加一,因为这里我们的dp数组的含义是最多包含m个0和n个1的string的最大子集个数,所以我们只能加一,用0-1背包类比的话,就是所有的物品的value都是1。

52. 携带研究材料(第七期模拟笔试) (kamacoder.com)

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的重量,并且具有不同的价值。

小明的行李箱所能承担的总重量是有限的,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料可以选择无数次,并且可以重复选择。

#include <iostream>
#include <vector>
using namespace std;
int main(){
    int n,badgeweights;
    cin>>n>>badgeweights;
    vector<int> weights(n+1);
    vector<int> values(n+1);
    for(int i=0;i<n;++i){
        cin>>weights[i]>>values[i];
    }
    vector<int> dp(badgeweights+1,0);
    for(int i=0;i<n;++i){
        for(int j=0;j<=badgeweights;++j){
            if(weights[i]<=j){
                dp[j]=max(dp[j],dp[j-weights[i]]+values[i]);
            }
        }
    }
    cout<<dp[badgeweights]<<endl;
    return 0;
}

这个就属于完全背包的问题了,所谓完全背包就是在0-1背包的基础上物品可以无限选择,主要带来的改动就是在遍历的过程中我们可以采取两个从小到大的遍历了:因为覆盖原来的值也无所谓。

518. 零钱兑换 II - 力扣(LeetCode)

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。 

题目数据保证结果符合 32 位带符号整数

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<uint64_t> dp(amount+1,0);
        dp[0]=1;
        for(int i=0;i<coins.size();++i){
            for(int j=coins[i];j<=amount;++j){
                dp[j]+=dp[j-coins[i]];
            }
        }
        return dp[amount];
    }
};

与目标和类似的一题,但是把背包替换成了完全背包,两题的递推公式是一样的:dp[j]+=dp[j-nums[i]];但是问题在于对背包的遍历:对于0-1背包,我们一般从后往前遍历:因为对于dp数组中的数来说,他们的值的变化依据来自于表左上方,也就是当前序号之前的值,如果从前往后遍历,容易反复使用;但对于完全背包来说,我们无所谓反复使用,甚至可以说需要反复使用,所以完全背包就是从前往后遍历。

377. 组合总和 Ⅳ - 力扣(LeetCode)

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

题目数据保证答案符合 32 位整数范围。

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        vector<unsigned long long> dp(target + 1, 0); // 使用更大的类型以防止溢出
        dp[0] = 1; // 只有当目标值为0时,有一种方法,即不选择任何数
        
        for (int j = 1; j <= target; ++j) { // 遍历所有可能的目标值
            for (int i = 0; i < nums.size(); ++i) { // 遍历所有可能的数字
                if (j >= nums[i]) { // 确保不会访问负索引
                    dp[j] += dp[j - nums[i]];
                }
            }
        }
        
        return dp[target];
    }
};

这个题与上述的完全背包求组合数又不一样:这个题求的是排列数!所谓组合和排列的区别只在于有无顺序,而反应在题目中,最大的区别就在于是先遍历物品还是先遍历背包。我们不妨这样想:如果我们先遍历物品,我们是根据物品填背包,物品是首先被考虑的,那么什么时候放进背包就不重要了,这就是组合;反之,我们先遍历背包,是根据背包来选物品,那么这个时候我们先放哪个物品进去都会对后续的背包选择物品产生影响,这就是排列。

57. 爬楼梯(第八期模拟笔试) (kamacoder.com)

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

每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢? 

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

#include <iostream>
#include <vector>
using namespace std;
int main(){
    int n,weights;
    cin>>n>>weights;
    vector<int> dp(n+1,0);
    dp[0]=1;
    for(int j=1;j<=n;++j){
        for(int i=1;i<=weights;++i){
            if(i<=j){
                dp[j]+=dp[j-i];
            }
        }
    }
    cout<<dp[n]<<endl;
    return 0;
}

又是一个求排列的题,并无太多特殊之处。

322. 零钱兑换 - 力扣(LeetCode)

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount+1,INT_MAX);
        dp[0]=0;
        for(int i=0;i<coins.size();++i){
            for(int j=coins[i];j<=amount;++j){
                if(dp[j-coins[i]]!=INT_MAX){
                    dp[j]=min(dp[j],dp[j-coins[i]]+1);
                }
            }
        }
        if(dp[amount]==INT_MAX)return -1;
        else return dp[amount];
    }
};

这个题和之前的要求又反过来了:要求最少的硬币数量,所以我们的递推公式需要变成求min,除此之外,我们还要注意我们的初始化条件:dp[0]=0,在这里dp的意义是最少的硬币数,所以我们针对0元的最少硬币自然是0;

279. 完全平方数 - 力扣(LeetCode)

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,149 和 16 都是完全平方数,而 3 和 11 不是。

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n + 1, INT_MAX);
        dp[0] = 0;
        for (int i = 0; i <= n; i++) { // 遍历背包
            for (int j = 1; j * j <= i; j++) { // 遍历物品
                dp[i] = min(dp[i - j * j] + 1, dp[i]);
            }
        }
        return dp[n];
    }
};

其实也是个经典的完全背包问题,我们的n就是背包容量,完全平方数就是物品,其weights是j*j,value是1。

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

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

相关文章

线性回归a

训练数据 求平方损失的平均值1/n&#xff0c;目标求解w&#xff0c;b使得损失函数最小 显示解

学习记录—正则表达式-基本语法

正则表达式简介-《菜鸟教程》 正则表达式是一种用于匹配和操作文本的强大工具&#xff0c;它是由一系列字符和特殊字符组成的模式&#xff0c;用于描述要匹配的文本模式。 正则表达式可以在文本中查找、替换、提取和验证特定的模式。 本期内容将介绍普通字符&#xff0c;特殊…

利用AI优化SEO关键词提升网站流量的有效策略

内容概要 在数字化时代&#xff0c;网站流量的增加对于任何企业或个人至关重要。为了在竞争激烈的市场中吸引更多用户&#xff0c;优化网站的SEO关键词显得尤为重要。随着人工智能技术的迅猛发展&#xff0c;它在SEO领域的应用也逐渐渗透&#xff0c;为关键词优化提供了新的可…

敏捷开发05:Sprint Planning 冲刺计划会议详细介绍和用户故事拆分、开发任务细分

Sprint Planning 冲刺计划会议简介 Sprint Planning &#xff08;冲刺计划会议&#xff09;&#xff0c;又叫规划会议。此会议通过 Scrum 团队的集体沟通讨论&#xff0c;确定接下来的 Sprint 中要完成的待开发项&#xff0c;把它们组成一个 Sprint Backlog。这些待开发项都是…

极简容器云WeKube快速体验

极简容器云WebKube快速体验 WeKube是什么&#xff1f; 概述 WeKube 是一个基于 Kubernetes 构建的极简Serverless容器服务&#xff0c;它提供了一个简单直观的方式来部署、管理和监控容器化的应用程序。WeKube 的目标是让用户无需关心底层基础设施的具体细节&#xff0c;而是…

Java开发经验——数据库开发经验

摘要 本文主要介绍了Java开发中的数据库操作规范&#xff0c;包括数据库建表规范、索引规约、SQL规范和ORM规约。强调了在数据库设计和操作中应遵循的最佳实践&#xff0c;如字段命名、数据类型选择、索引创建、SQL语句编写和ORM映射&#xff0c;旨在提高数据库操作的性能和安…

ovirt-engine登录报错

ovirt-engine登录报错 注&#xff1a;用户名不是admin&#xff0c;而是adminlocalhost

windows nmake 安装openssl

windows nmake 编译和安装 openssl 本文提供了在Windows环境下安装OpenSSL的详细步骤&#xff0c;包括下载Perl、NASM和VisualStudio&#xff0c;配置环境变量&#xff0c;使用PerlConfigure设置平台&#xff0c;通过nmake进行编译、测试和安装。整个过程涉及32位和64位版本的选…

智能家居实训室中,STC单片机驱动的“互联网+”智能家居系统设计

一、引言 随着经济的快速发展&#xff0c;人们对家居环境的智能化、网络化需求日益增强&#xff0c;智能家居的研究也因此受到了国内外相关机构的广泛关注。STC单片机凭借其卓越的性能和广泛的应用领域&#xff0c;成为了智能家居系统设计的优选方案。作为一种先进的微控制器&…

分析排名靠前的一些自媒体平台,如何运用这些平台?

众所周知&#xff0c;现在做网站越来越难了&#xff0c;主要的原因还是因为流量红利时代过去了。并且搜索引擎都在给自己的平台做闭环改造。搜索引擎的流量扶持太低了。如百度投资知乎&#xff0c;给知乎带来很多流量扶持&#xff0c;也为自身内容不足做一个填补。 而我们站长…

[计算机网络]OSPF协议

开放最短路径优先OSPF 1&#xff09;OSPF的工作方式 1>和谁交换消息 使用洪泛法&#xff0c;向本自治系统的所有路由器发送消息。 2>交换什么消息 发送的消息就是与本路由器相邻的所有路由器的链路状态&#xff0c;但这只是路由器所知道的部分信息。 链路状态就是说…

攻防世界PWN刷题笔记(引导模式)1-3

感谢组长和其他高手让我入门学pwn&#xff0c;个人感觉做题和看课程应该一块推进&#xff0c;光看课程&#xff0c;容易疲乏&#xff0c;而且缺乏经验。只做题&#xff0c;学的知识缺乏体系&#xff0c;因此决定立志每天看课&#xff0b;做题&#xff08;先保证不挂科的前提下&…

【机器学习案列】车牌自动识别系统:基于YOLO11的高效实现

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

upload-labs关卡记录12

直接上传一句话木马&#xff0c;发现提示&#xff1a; 很明显这是一个白名单&#xff0c;而且不是前端的js检查&#xff0c;而是服务端的检查&#xff0c;因此我们使用bp抓包&#xff0c;改一下文件类型试试&#xff1a; 找到包之后&#xff0c;我们对content-type进行一个更改…

3、计算机中数制与码制

计算机中的数据是以二进制存储&#xff0c;但是日常使用的数据为十进制&#xff0c;除了十进制还有八进制和十六进制。它们之间存在一定的转化关系。 1、数制间转换 一个数据可以有不同的表现形式&#xff0c;比如&#xff1a; 1.1、十进制转二进制 十进制转其他进制可以使用短…

【Qt】基础(命名风格、文档查看、坐标体系、控件位置设置和获取)

1.命名风格 Qt中偏好用小驼峰&#xff0c;来命名变量/函数&#xff0c;用大驼峰命名类。 2.文档使用 2.1 光标移动到类型或方法&#xff0c;按F1。自动打开对应文档。 2.2 在帮助中打开整个文档 2.3 开始查询Assistant 3.Qt窗口坐标体系 1.左手坐标系 原点为左上角&#x…

【递归,搜索与回溯算法 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)

优美的排列 题目解析 算法原理 解法 &#xff1a;暴搜 决策树 红色剪枝&#xff1a;用于剪去该节点的值在对应分支中&#xff0c;已经被使用的情况&#xff0c;可以定义一个 check[ ] 紫色剪枝&#xff1a;perm[i] 不能够被 i 整除&#xff0c;i 不能够被 per…

OpenCV putText增加中文支持

OpenCV 默认并不支持中文字符显示&#xff0c;需要增加 freetype 支持&#xff0c;也需正确设置中文字体才能正常显示中文。 OpenCV 2.x 版本没有该模块&#xff0c;而 OpenCV 3.x 及以上版本才正式引入了 freetype 模块 &#xff0c;可检查并更新到较新且包含该模块的版本。 O…

光谱相机与普通相机的区别

一、成像目的 普通相机&#xff1a;主要目的是记录物体的外观形态&#xff0c;生成人眼可见的、直观的二维图像&#xff0c;重点在于还原物体的形状、颜色和纹理等视觉特征&#xff0c;以供人们进行观赏、记录场景或人物等用途。例如&#xff0c;拍摄旅游风景照片、人物肖像等…

爬虫 APP 逆向 ---> shopee(虾皮) 电商

shopee 泰国站点&#xff1a;https://shopee.co.th/ shopee 网页访问时&#xff0c;直接弹出使用 app 登录查看&#xff0c;那就登录 shopee 泰国站点 app。 手机抓包&#xff1a;分类接口 接口&#xff1a;https://mall.shopee.co.th/api/v4/pages/get_category_tree 请求参…