动态规划 - 4( 背包问题 10000 字详解 )

news2025/1/17 4:09:30

一: 背包问题

1.1 01 背包

题目链接:01 背包

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
    	// 不做空间优化,用 dp 表存下所有状态
        Scanner sc = new Scanner(System.in);

        // 读入 n 和 V
        int n = sc.nextInt();
        int V = sc.nextInt();

        // 定义物品的体积 v 和价值 w
        int[] v = new int[n + 1];  // 体积数组
        int[] w = new int[n + 1];  // 价值数组

        for (int i = 1; i <= n; i++) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }

        // dp 数组,用于存储当前背包容量下的最大价值
        int[][] dp = new int[n + 1][V + 1];

        // 解决第一个问题(最大价值问题)
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= V; j++) {
                dp[i][j] = dp[i - 1][j]; // 不选当前物品
                if (j >= v[i]) {
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - v[i]] + w[i]); // 选当前物品
                }
            }
        }
        System.out.println(dp[n][V]);

        // 解决第二个问题(是否能正好装满背包)
        // 清空 dp 数组
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= V; j++) {
                dp[i][j] = 0;
            }
        }

        // 初始化背包容量为 0 的状态为 -1,表示不可达
        for (int j = 1; j <= V; j++) {
            dp[0][j] = -1;  // 0 物品,容量 j 不可能达到
        }

        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= V; j++) {
                dp[i][j] = dp[i - 1][j]; // 不选当前物品
                if (j >= v[i] && dp[i - 1][j - v[i]] != -1) {
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
                }
            }
        }

        // 如果 dp[n][V] == -1,表示无法正好装满背包,输出 0;否则输出最大价值
        System.out.println(dp[n][V] == -1 ? 0 : dp[n][V]);

        sc.close();
    }
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
    	// 利用滚动数组进行空间优化
        Scanner sc = new Scanner(System.in);

        // 读入 n 和 V
        int n = sc.nextInt();
        int V = sc.nextInt();

        // 定义物品的体积 v 和价值 w
        int[] v = new int[n + 1];  // 物品体积数组
        int[] w = new int[n + 1];  // 物品价值数组

        for (int i = 1; i <= n; i++) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }

        // dp 数组,用于存储当前背包容量下的最大价值
        int[] dp = new int[V + 1];

        // 解决第一个问题(01背包问题)
        // 从后往前遍历背包容量,以确保每个物品只使用一次
        for (int i = 1; i <= n; i++) {
            for (int j = V; j >= v[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - v[i]] + w[i]);
            }
        }
        System.out.println(dp[V]);

        // 解决第二个问题(是否能够正好装满背包)
        // 清空 dp 数组
        for (int i = 0; i <= V; i++) {
            dp[i] = 0;
        }

        // 初始化背包容量为 0 的状态为 -1,表示不可达
        for (int j = 1; j <= V; j++) {
            dp[j] = -1;
        }

        for (int i = 1; i <= n; i++) {
            for (int j = V; j >= v[i]; j--) {
                if (dp[j - v[i]] != -1) {
                    dp[j] = Math.max(dp[j], dp[j - v[i]] + w[i]);
                }
            }
        }

        // 如果 dp[V] == -1,表示无法正好装满背包,输出 0;否则输出最大价值
        System.out.println(dp[V] == -1 ? 0 : dp[V]);

        sc.close();
    }
}

在这里插入图片描述

1.2 分割等和子集

题目链接:分割等和子集

在这里插入图片描述
在这里插入图片描述

class Solution {
    public boolean canPartition(int[] nums) {
        // 采用动态规划的思想解决问题,首先计算一下这个数组的总和,并处理一下特殊的情况
        int sum = 0;
        for(int x : nums) sum += x;
        if(sum % 2 == 1) return false;

        // 接下来开始创建一个 dp 表,dp[i][j] 表示在前 i 个元素中是否能组成和为 j 的子集
        int n = nums.length, aim = sum / 2;
        boolean[][] dp = new boolean[n + 1][aim + 1];

        // 接着初始化一下第一列
        for(int i = 0; i <= n; i++)
            dp[i][0] = true;
        
        // 初始化完成后就可以从上往下开始填表了
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= aim; j++){
                // 注意下标映射
                dp[i][j] = dp[i - 1][j];  // 默认不选择当前元素,继承上一行的状态
                if(j >= nums[i - 1]) dp[i][j] = dp[i][j] || dp[i - 1][j - nums[i - 1]]; 
            }
        }

        return dp[n][aim];
    }
}
class Solution {
    public boolean canPartition(int[] nums) {
        // 采用动态规划的思想解决问题,并采用滚动数组进行优化
        // 首先统计一下 nums 数组的总和,并处理一下特殊情况
        int sum = 0; 
        for(int x : nums) sum += x;
        if(sum % 2 == 1) return false;

        // 接着创建一个 dp 表,dp[j] 表示是否可以用某些元素组成和为 j 的子集
        int aim = sum / 2, n = nums.length;
        boolean[] dp = new boolean[aim + 1];

        // 接着初始化 dp 表
        dp[0] = true;

        // 因为填表需要 nums 中的元素和 dp 表的元素,所以两层 for 循环固定两个数
        //  逐个遍历 nums 数组中的每个元素
        for(int i = 1; i <= n; i++){
            //  从后往前填表,因为要防止 dp 表被重复使用和 dp 表的值被覆盖
            //  如果 j 小于 nums[i - 1],那么 j - nums[i - 1] 会变成负数,这样的索引是无效的,,因此在内层循环中应该从 j = aim 开始,直到 j >= nums[i - 1] 结束,此时 dp[j] 天然满足 j >= nums[i - 1] 条件
            for(int j = aim; j >= nums[i - 1]; j--){
                dp[j] = dp[j] || dp[j - nums[i - 1]];
            }
        }

        return dp[aim];
    }
}

在这里插入图片描述

1.3 目标和

题目链接:目标和

在这里插入图片描述
在这里插入图片描述

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        // 采用动态规划的思想解决问题,首先求一下 a 的值并处理一下特殊情况
        int sum = 0;
        for(int x : nums) sum += x;
        int a = (sum + target) / 2;
        if(a < 0 || (sum + target) % 2 == 1) return 0;

        // 接着创建并初始化 dp 表
        int n = nums.length;
        int[][] dp = new int[n + 1][a + 1];
        dp[0][0] = 1;

        // 接着就可以从上往下开始填表了,从 1 开始是因为我们需要逐步考虑每个元素
        for(int i = 1; i <= n; i++){
            // 从和为 0 开始,逐渐更新所有可能的和
            for(int j = 0; j <= a; j++){
                // 默认为不选,注意下标映射关系
                dp[i][j] = dp[i - 1][j];
                if(j >= nums[i - 1]) dp[i][j] += dp[i - 1][j - nums[i - 1]];
            }
        }

        return dp[n][a];
    }
}
class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        // 采用动态规划的思想解决问题,并用滚动数组进行空间优化
        int sum = 0, n = nums.length;
        for(int x : nums) sum += x;
        int aim = (sum + target) / 2;
        if(aim < 0 || (sum + target) % 2 == 1) return 0;

        // 接着创建一个 dp 表,dp[j] 表示和为 j 的组合数
        int[] dp = new int[aim + 1];
        dp[0] = 1;

        // 接着开始填表,外层循环遍历 nums 中的每个元素
        for(int i = 1; i <= n; i++){
            // 内层循环从后往前填表
            for(int j = aim; j >= nums[i - 1]; j--){
                dp[j] += dp[j - nums[i - 1]];
            }
        }

        return dp[aim];
    }
}

在这里插入图片描述

1.4 最后一块石头的重量 II

题目链接:最后一块石头的重量 II
在这里插入图片描述
在这里插入图片描述

class Solution {
    public int lastStoneWeightII(int[] stones) {
        // 采用动态规划的思想解决问题,首先求一下 stones 数组的总和
        int sum = 0;
        for(int x : stones) sum += x;

        // 接着创建一个 dp 表,dp[i][j] 表示前 i 个石头中,和为 j 的最大子集和,m 是我们想要找到的最接近 sum / 2 的子集和
        int m = sum / 2, n = stones.length;
        int[][] dp = new int[n + 1][m + 1];

        // 因为要初始化的地方都为 0 ,所以直接跳过,进入填表
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                // 默认为不选
                dp[i][j] = dp[i - 1][j];
                if(j >= stones[i - 1]) dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - stones[i - 1]] + stones[i - 1]);
            }
        }
        
        return sum - 2 * dp[n][m];
    }
}
class Solution {
    public int lastStoneWeightII(int[] stones) {
        // 采用动态规划的思想解决问题,首先求一下 stones 数组的总和,并用滚动数组进行空间优化
        int sum = 0;
        for(int x : stones) sum += x;

        // 接着创建一个 dp 表,dp[i][j] 表示前 i 个石头中,和为 j 的最大子集和,m 是我们想要找到的最接近 sum / 2 的子集和
        int m = sum / 2, n = stones.length;
        int[] dp = new int[m + 1];

        // 因为要初始化的地方都为 0 ,所以直接跳过,进入填表
        for(int i = 1; i <= n; i++){
            for(int j = m; j >= stones[i - 1]; j--){
                dp[j] = Math.max(dp[j], dp[j - stones[i - 1]] + stones[i - 1]);
            }
        }
        
        return sum - 2 * dp[m];
    }
}

在这里插入图片描述

1.5 完全背包

题目链接:完全背包

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        // 读入物品个数和背包容量
        int n = in.nextInt(); // 物品数量
        int V = in.nextInt(); // 背包容量

        // 创建数组,分别保存物品的体积、价值
        int[] v = new int[n + 1]; // 物品体积数组
        int[] w = new int[n + 1]; // 物品价值数组

        // dp[i][j] 表示前 i 个物品,在背包容量为 j 时能获得的最大价值
        int[][] dp = new int[n + 1][V + 1];

        // 读入每个物品的体积和价值
        for (int i = 1; i <= n; i++) {
            v[i] = in.nextInt(); // 物品的体积
            w[i] = in.nextInt(); // 物品的价值
        }

        // 完全背包问题:求最大价值
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= V; j++) {
                dp[i][j] = dp[i - 1][j]; // 不选择当前物品
                if (j >= v[i]) { // 如果当前背包容量大于等于当前物品的体积
                    dp[i][j] = Math.max(dp[i][j], dp[i][j - v[i]] + w[i]); // 选择当前物品
                }
            }
        }

        // 输出第一个问题的结果:背包容量为 V 时的最大价值
        System.out.println(dp[n][V]);

        // 第二个问题:判断能否完全填满背包
        // 初始化 dp 数组
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= V; j++) {
                dp[i][j] = 0; // 先将所有的 dp 值初始化为 0
            }
        }

        // 特殊初始化:当背包容量为 0 时,最大价值为 0
        dp[0][0] = 0;

        // 初始化 dp 数组,将不可能填满的容量标记为 -1
        for (int j = 1; j <= V; j++) {
            dp[0][j] = -1; // dp[0][j] == -1 表示不可能填满背包
        }

        // 动态规划:填充 dp 数组,判断是否能够填满背包
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= V; j++) {
                dp[i][j] = dp[i - 1][j]; // 不选当前物品
                if (j >= v[i] && dp[i][j - v[i]] != -1) { // 如果能选择当前物品并且能填满剩余的背包
                    dp[i][j] = Math.max(dp[i][j], dp[i][j - v[i]] + w[i]); // 更新 dp[i][j] 为最大价值
                }
            }
        }

        // 输出第二个问题的结果:若无法填满背包,输出 0,否则输出最大价值
        System.out.println(dp[n][V] == -1 ? 0 : dp[n][V]);

        in.close(); // 关闭输入流
    }
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        // 读入数据
        int n = in.nextInt(); // 物品个数
        int V = in.nextInt(); // 背包容量
        int[] v = new int[n + 1]; // 物品体积
        int[] w = new int[n + 1]; // 物品价值
        int[] dp = new int[V + 1]; // dp[i]表示背包容量为i时的最大价值

        // 读入每个物品的体积和价值
        for (int i = 1; i <= n; i++) {
            v[i] = in.nextInt(); // 物品体积
            w[i] = in.nextInt(); // 物品价值
        }

        // 第一个问题:完全背包问题,求最大价值
        for (int i = 1; i <= n; i++) {
            for (int j = v[i]; j <= V; j++) {
                dp[j] = Math.max(dp[j], dp[j - v[i]] + w[i]);
            }
        }
        System.out.println(dp[V]); // 输出第一个问题的结果

        // 第二个问题:判断能否填满背包,输出最大价值或0
        // 重置 dp 数组
        for (int i = 0; i <= V; i++) {
            dp[i] = Integer.MIN_VALUE; // 初始化为极小值,表示无法填满背包
        }

        // 初始状态,第0个物品时的背包容量
        dp[0] = 0; // 背包容量为0时的最大价值为0

        // 完全背包动态规划过程
        for (int i = 1; i <= n; i++) {
            for (int j = v[i]; j <= V; j++) {
                dp[j] = Math.max(dp[j], dp[j - v[i]] + w[i]);
            }
        }

        // 如果 dp[V] < 0,表示无法填满背包,输出 0,否则输出最大价值
        System.out.println(dp[V] < 0 ? 0 : dp[V]);

        // 关闭输入流
        in.close();
    }
}

在这里插入图片描述

1.6 零钱兑换

题目链接:零钱兑换

在这里插入图片描述
在这里插入图片描述

class Solution {
    public int coinChange(int[] coins, int amount) {
        // 采用动态规划的思想解决问题,首先创建一个 dp 表, dp[i][j] 表示使用前 i 个硬币来凑成金额 j 的最小硬币数
        int n = coins.length, INF = 0x3f3f3f3f; // INF 表示正无穷大
        int[][] dp = new int[n + 1][amount + 1];

        // 接着开始初始化
        for(int j = 1; j <= amount; j++)
            dp[0][j] = INF;
        
        // 初始化完成后开始从上往下,从左往右填表
        for(int i = 1; i <= n; i++){
            for(int j = 0; j <= amount; j++){
                // 默认为不选
                dp[i][j] = dp[i - 1][j];
                if(j >= coins[i - 1]) dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - coins[i - 1]] + 1);
            }
        }

        return dp[n][amount] >= INF ? -1 : dp[n][amount];
    }
}
class Solution {
    public int coinChange(int[] coins, int amount) {
        // 采用动态规划的思想解决问题,并用滚动数组进行空间优化,首先创建一个 dp 表, dp[i][j] 表示使用前 i 个硬币来凑成金额 j 的最小硬币数
        int n = coins.length, INF = 0x3f3f3f3f; // INF 表示正无穷大
        int[] dp = new int[amount + 1];

        // 接着开始初始化
        for(int j = 1; j <= amount; j++)
            dp[j] = INF;
        
        // 初始化完成后开始从上往下,从左往右填表
        for(int i = 1; i <= n; i++){
        	// 在这个问题中,我们没有限制一个硬币只能用一次,因此可以按照 从左到右 的顺序填表。
        	// 每次更新 dp[j] 时,其实是基于之前的 dp[j - coins[i - 1]],而 dp[j - coins[i - 1]] 只依赖于上一轮的状态,所以可以安全地在顺序填表时更新。
            for(int j = coins[i - 1]; j <= amount; j++){
                dp[j] = Math.min(dp[j], dp[j - coins[i - 1]] + 1);
            }
        }

        return dp[amount] >= INF ? -1 : dp[amount];
    }
}

在这里插入图片描述

1.7 零钱兑换 II

题目链接:零钱兑换 II
在这里插入图片描述
在这里插入图片描述

class Solution {
    public int change(int amount, int[] coins) {
        // 采用动态规划的思想解决这个问题,首先创建一个 dp 表,dp[i] 表示金额 i 的组合数
        int[] dp = new int[amount + 1];

        // 接着初始化 dp 
        dp[0] = 1;

        // 接着开始从上往下,从左往右填表
        for(int i = 0; i < coins.length; i++){
            for(int j = coins[i]; j <= amount; j++){
                 dp[j] += dp[j - coins[i]];
            }
        }

        return dp[amount];
    }
}

在这里插入图片描述

1.8 完全平方数

题目链接:完全平方数
在这里插入图片描述
在这里插入图片描述

class Solution {
    public int numSquares(int n) {
        // 首先创建并初始化 dp 表,dp 表用于存储每个数的最小完全平方数的个数
        int[] dp = new int[n + 1];
        dp[1] = 1; 

        for (int i = 2; i <= n; i++) {
            dp[i] = 1 + dp[i - 1]; 

            for (int j = 2; j * j <= i; j++) 
                dp[i] = Math.min(dp[i], dp[i - j * j] + 1); 
            
        }

        return dp[n];
    }
}

在这里插入图片描述

二: 二维费用的背包问题

2.1 一和零

题目链接:二维费用的背包问题 一和零
在这里插入图片描述
在这里插入图片描述

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        // 采用动态规划的思想解决问题,首先创建一个 dp 表,dp[i][j][k],表示考虑前 i 个字符串,用 j 个 '0' 和 k 个 '1' 的情况下,能组成的最大字符串个数
        int len = strs.length;
        int[][][] dp = new int[len + 1][m + 1][n + 1];

        // 因为无需初始化,所以直接开始填表,填表保证 i 从小到大
        for (int i = 1; i <= len; i++) {
            int a = 0, b = 0; // a 表示 '0' 的个数,b 表示 '1' 的个数
            for (char ch : strs[i - 1].toCharArray()) {
                if (ch == '0') a++;  
                else b++;  
            }

            for (int j = 0; j <= m; j++) {  
                for (int k = 0; k <= n; k++) {  
                    dp[i][j][k] = dp[i - 1][j][k];  // 默认为不选择当前字符串的情况
                    if (j >= a && k >= b)  dp[i][j][k] = Math.max(dp[i][j][k], dp[i - 1][j - a][k - b] + 1);
                }
            }
        }

        return dp[len][m][n];
    }
}
class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        // 采用动态规划的思想解决问题,并用滚动数组进行优化
        // 首先创建一个 dp 表,dp[j][k],表示使用 j 个 '0' 和 k 个 '1' 能够组成的最大子集数量
        int len = strs.length;
        int[][] dp = new int[m + 1][n + 1];
        
        // 接着统计字符串 '0' 和 '1' 的个数,并更新 dp 数组
        for (int i = 1; i <= len; i++) {
            int a = 0, b = 0;
            for (char ch : strs[i - 1].toCharArray()) {
                if (ch == '0') a++;  
                else b++;             
            }

            for (int j = m; j >= a; j--) {   
                for (int k = n; k >= b; k--) { 
                    dp[j][k] = Math.max(dp[j][k], dp[j - a][k - b] + 1);
                }
            }
        }
        
        return dp[m][n];
    }
}

在这里插入图片描述

2.2 盈利计划

题目链接: 盈利计划

在这里插入图片描述
在这里插入图片描述

class Solution {
    public int profitableSchemes(int n, int m, int[] g, int[] p) {
        // 首先创建一个 dp 表,dp[i][j][k] 表示前 i 个工作,选择了 j 人,赚取了 k 利润的方案数
        int len = g.length;  
        int MOD = (int) 1e9 + 7;  // 因为结果需要对 10^9 + 7 取模,所以定义一个 MOD 变量
        int[][][] dp = new int[len + 1][n + 1][m + 1];  

        // 初始化一下 dp 表
        for (int j = 0; j <= n; j++) 
            dp[0][j][0] = 1;
        

        // 接着开始填表
        for (int i = 1; i <= len; i++) {  
            for (int j = 0; j <= n; j++) {  
                for (int k = 0; k <= m; k++) { 
                    dp[i][j][k] = dp[i - 1][j][k];  // 默认不选择当前工作 i 的方案数
                    if (j >= g[i - 1])  dp[i][j][k] += dp[i - 1][j - g[i - 1]][Math.max(0, k - p[i - 1])];
                    // 由于可能存在溢出,方案数需要对 10^9 + 7 取模
                    dp[i][j][k] %= MOD;
                }
            }
        }

        return dp[len][n][m];
    }
}
class Solution {
    public int profitableSchemes(int n, int m, int[] g, int[] p) {
        // 采用动态规划的思想解决问题,并用滚动数组进行优化,首先创建一个 dp 表,dp[j][k] 表示雇佣 j 个人并赚取 k 利润的方案数
        int len = g.length;  
        int MOD = (int) 1e9 + 7;  // 因为结果需要对 10^9 + 7 取模,所以定义一个 MOD 变量
        int[][] dp = new int[n + 1][m + 1]; 

        // 初始化一下 dp 表
        for (int j = 0; j <= n; j++) 
            dp[j][0] = 1;
        

        // 接着开始填表
        for (int i = 1; i <= len; i++) {  
            for (int j = n; j >= g[i - 1]; j--) {  
                for (int k = m; k >= 0; k--) { 
                    dp[j][k] += dp[j - g[i - 1]][Math.max(0, k - p[i - 1])];
                    // 由于可能存在溢出,方案数需要对 10^9 + 7 取模
                    dp[j][k] %= MOD;
                }
            }
        }

        return dp[n][m];
    }
}

在这里插入图片描述

三:似包非包

3.1 组合总和 IV

题目链接:组合总和 IV
在这里插入图片描述
在这里插入图片描述

class Solution {
    public int combinationSum4(int[] nums, int target) {
        // 采用动态规划的思想解决问题,首先创建一个 dp 表,dp[i] 表示组成目标 i 的组合数
        int[] dp = new int[target + 1]; 

        // 接着初始化 dp 表
        dp[0] = 1; 
        
        // 接着开始从左往右填表
        for (int i = 1; i <= target; i++) {
            for (int x : nums) {
                if (i >= x)  dp[i] += dp[i - x];        
            }
        }

        return dp[target];
    }
}

在这里插入图片描述

3.2 不同的二叉搜索树

题目链接:不同的二叉搜索树

在这里插入图片描述
在这里插入图片描述

class Solution {
    public int numTrees(int n) {
        // 采用动态规划的思想解决问题,首先创建一个 dp 表,dp[i] 表示由 i 个节点组成的不同 BST 的数量
        int[] dp = new int[n + 1]; 

        // 初始化 dp 表
        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];
    }
}

在这里插入图片描述

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

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

相关文章

关于利用 EtherNet/IP 转 Profinet 网关模块实现罗克韦尔变频器接入西门子 PLC 的配置范例

在现代工业自动化领域&#xff0c;不同品牌设备之间的通信兼容性问题一直是企业面临的挑战之一。某智能工厂为了优化生产流程&#xff0c;提高设备的协同工作效率&#xff0c;决定对其生产线上的控制系统进行升级改造。该生产线中&#xff0c;AB罗克韦尔PowerFlex变频器作为关键…

论文研读|信息科技风险管理模型的主要内容、定位、目标企业、风险管理机制, 以及相应的风险评估流程和风险应对策略

文献来源&#xff1a;[1]李政.商业银行数据中心风险管理研究[D].合肥工业大学[2024-12-08]. 内容总结&#xff1a;风险管理是一项不断发展完善的体系化工作。本章研究了国际上普遍使用的风险管理基本模型、并针对主流的信息科技风险管理的框架进行研究、分析&#xff0c;重点研…

MySQL-DML之数据表操作

文章目录 一. 插入表记录1. 向表中插入部分字段2. 向表中插入所有字段,字段的顺序为创建表时的顺序3. 一次添加多条数据信息 二. 更新表记录1. 更新所有记录的指定字段 更新符号条件记录的指定字段2. 更新符号条件记录的指定字段 三. 删除表记录1. 按条件删除记录2. 清空记录 四…

mac mini 4 上手指南

文章目录 和 mac 初见购机历程外设配置win 系统 适应 mac 系统一些使用体验mac 快捷键 和 mac 初见 最开始用 mac 是小时候用着刷成 windows 的 MacBook 和好朋友一起打游戏&#xff0c;再后来就是上大学&#xff0c;用朋友的 mac 做一些简单的办公 购机历程 我之前 11月2日…

Apache AGE:基于PostgreSQL的图数据库

Apache AGE&#xff08;A Graph Extension&#xff09;是一个基于 PostgreSQL 的图数据库。它以扩展插件的形式提供&#xff0c;可以在利用 PostgreSQL 先进的 SQL 查询功能和事务支持的同时&#xff0c;享受图数据库的灵活性和可扩展性。 Apache AGE 最初由 Bitnine Global In…

关于springBoot+vue项目中配置SSL证书问题

前端可以通过https进行访问 1.前端在访问后端接口时&#xff0c;使用https进行访问&#xff0c;在request.js配置文件中&#xff0c;这个文件是配置axios的基本请求的&#xff0c;在基础请求地址中改为https方式 2.需要在Linux中的nginx中配置ssl证书&#xff0c;具体请参考&…

华为、华三交换机纯Web下如何创关键VLANIF、操作STP参数

华为交换机WEB操作 使用的是真机S5735&#xff0c;目前主流的版本都适用&#xff08;V1R5~V2R1的就不在列了&#xff0c;版本太老了&#xff0c;界面完全不一样&#xff0c;这里调试线接的console口&#xff0c;电脑的网络接在ETH口&#xff09; 「模拟器、工具合集」复制整段内…

二分查找(带图详解)

优选算法系列 文章目录 优选算法系列前言一、二分查找的思想二、算法使用小总结 三、代码实现四、二分查找拓展4.1、查找第一次出现的target小总结 4.2、target最后出现的位置小总结 五、代码总结 前言 在这篇博客中&#xff0c;我会给大家分享二分查找及其扩展。 这是链接-&…

【C#】NET 9中LINQ的新特性-CountBy

前言 在 .NET 中,使用 LINQ 对元素进行分组并计算它们的出现次数时,需要通过两个步步骤。首先,使用 GroupBy方法根据特定键对元素进行分类。然后,再计算每个组元素包含个数。而随着 .NET 9 版本发布,引入了一些新特性。其中 LINQ 引入了一种新的方法 CountBy,本文一起来了…

[SWPUCTF 2022 新生赛]funny_php

进入靶场环境 <?phpsession_start();highlight_file(__FILE__);if(isset($_GET[num])){if(strlen($_GET[num])<3&&$_GET[num]>999999999){echo ":D";$_SESSION[L1] 1;}else{echo ":C";}}if(isset($_GET[str])){$str preg_replace(/NS…

2024-10-13-B fd 重定向 缓冲区

1 一切皆文件 1.1 虚拟文件系统 在系统层面&#xff0c;做了一层软件的封装&#xff0c;struct file 里有操作表&#xff08;即函数指针的集合&#xff09;&#xff0c;可以调用底层的读写方法。虚拟文件系统&#xff08;VFS&#xff09;是一种神奇的抽象&#xff0c;它使得…

调整数组顺序使奇数位于偶数前面

题目 输入一个整数数组&#xff0c;调整数组中数字的顺序&#xff0c;使得所有奇数位于数组的前半部分&#xff0c;所有偶数位于数组的后半部分。要求时间复杂度为O(n) 解法 双指针i和j 指针i起点是数组起点&#xff0c;当i检测到偶数时停下。j的起点时数组终点&#xff0c;…

如何使用 Docker Compose 安装 Memos 自托管笔记应用

简介 Memos是一个自托管的开源笔记应用程序&#xff0c;专为个人组织和信息管理而设计。它允许用户高效地创建、存储和管理笔记&#xff0c;提供如Markdown支持、用户友好的界面和注重隐私的设计等功能。Memos可以在各种平台上运行&#xff0c;但使用Docker Compose可以简化部…

详解:HTTP/HTTPS协议

HTTP协议 一.HTTP是什么 HTTP&#xff0c;全称超文本传输协议&#xff0c;是一种用于分布式、协作式、超媒体信息系统的应用层协议。HTTP往往是基于传输层TCP协议实现的&#xff0c;采用的一问一答的模式&#xff0c;即发一个请求&#xff0c;返回一个响应。 Q&#xff1a;什…

小程序项目的基本组成结构

分类介绍 项目根目录下的文件及文件夹 pages文件夹 用来存放所有小程序的页面&#xff0c;其中每个页面都由4个基本文件组成&#xff0c;它们分别是&#xff1a; .js文件&#xff1a;页面的脚本文件&#xff0c;用于存放页面的数据、事件处理函数等 .json文件&#xff1a;…

【uni-app 微信小程序】新版本发布提示用户进行更新

知识准备 uni.getUpdateManager文档介绍 不支持APP与H5&#xff0c;所以在使用的时候要做好平台类型的判断&#xff0c;如何判断&#xff0c;参考条件编译处理多端差异 代码参考 export const updateApp () > {const updateManager uni.getUpdateManager()updateManag…

LabVIEW断路器检测系统

随着电网技术的快速发展&#xff0c;对电力系统的可靠性和安全性要求不断提高&#xff0c;塑壳断路器作为关键的保护设备&#xff0c;其出厂前的检测非常重要。开发了一种基于LabVIEW软件平台开发的塑壳断路器智能脱扣器检测系统&#xff0c;该系统能够有效提高检测的自动化水平…

ASP.NET Core API 前后端分离跨域

环境准备 数据库&#xff1a; sqlserver 2022 后端&#xff1a; vs2022 ASP.NET Core API .net 8 前端&#xff1a; Hbuilderx bootstrap 5.3.0 jquery v3.7.1 bootstrap-table 1.23.5 完整项目代码下载地址 功能 实现 单张表 的 增 删 改 查 创建数据库和表 create data…

Mac M1 安装数据库

1. Docker下载 由于Sqlserver和达梦等数据库&#xff0c;不支持M系列的芯片&#xff0c;所以我们通过docker安装 下载并安装docker: https://www.docker.com/get-started/ 安装完成后&#xff0c;打开docker 2. SQL Server 安装 2.1 安装 打开终端&#xff0c;执行命令 doc…

进程的管理与控制

一、进程与线程 1. 进程 程序&#xff1a;是静态的&#xff0c;就是个存放在磁盘里的可执行文件&#xff0c;就是一系列的指令集合。 进程&#xff08;Process&#xff09;&#xff1a;是指计算机中已执行的程序&#xff0c;是动态的。 &#xff08;1&#xff09;进程的组成…