动态规划思想-01背包图解案例

news2025/2/25 9:48:26

动态规划介绍

动态规划基本思想

​ 动态规划将一个问题分解为若干个互相重叠的子问题,并通过存储子问题的解来避免重复计算,从而大幅提升时间效率。

​ 跟分治有些类似(“”与“”体现在 状态转移方程),但是通常这些子问题都相互重叠。

​ 所以动态规划的重点就是找到这个递推关系,即较小规模问题如何推断出更大问题的解。

判断一个问题是否可以使用动态规划解决

1、最优子结构

​ 原问题的最优解是从子问题的最优解构建得来的。

​ 从状态的角度理解,就是后面阶段的状态可以由前面阶段的状态推导出来。

2、无后效性

​ 给定一个确定的状态,它的未来发展只与当前状态有关,而与过去经历的所有状态无关。

​ 换句话说,各个子问题的只与它前面的子问题的解相关。而且各子问题的解都是相对于当前状态的最优解,整个问题的最优解是由各个子问题的最优解构成。

3、重叠子问题

​ 重叠子问题是指在问题的求解过程中,会反复遇到相同的子问题。这些子问题可能在不同的情况下多次出现,但其解决方法是相同的。

动态规划求解过程

1、划分子问题(定义初始状态)

​ 将原问题分解为若干个子问题,每个子问题对应一个决策阶段,并且这些子问题直接具有重叠关系。这一步主要就是定义初始状态。

2、确定动态规划函数(状态转移方程)

​ 找出最优子结构,然后根据子问题直接的重叠关系找到子问题之间的递推关系,这一步是动态规划的关键。

3、填表

​ 设计表格,自底向上计算各个子问题的解并填写DP表。

数学归纳法

​ 其实,动态规划的思想就像是数学归纳法的思想,状态转移方程就像是数学归纳法的递推函数,定义初始状态就像是数学归纳法中的初始状态一样。

简单回顾一下数学归纳法:

证明前n项和 S ( n ) = 1 + 2 + 3 … . + n = n ∗ ( n + 1 ) / 2 S(n) = 1 + 2 + 3 …. + n = n*(n + 1) / 2 S(n)=1+2+3.+n=n(n+1)/2

1、确定初始状态: n = 1 , S ( 1 ) = 1 = 1 ∗ ( 1 + 1 ) / 2 n = 1, S(1) = 1 = 1*(1+1) /2 n=1,S(1)=1=1(1+1)/2

2、确定递推关系 S ( n ) = n ∗ ( n + 1 ) / 2 S(n) = n*(n + 1) / 2 S(n)=n(n+1)/2

​ 假设n=n时命题成立,那么对于n+1来说:

S ( n + 1 ) = S ( n ) + n + 1 = n ( n + 1 ) / 2 + n + 1 = ( n + 1 ) [ ( n + 1 ) + 1 ] / 2 S(n + 1) = S(n) + n + 1= n(n + 1)/2 + n + 1= (n + 1)[(n + 1)+1]/ 2 S(n+1)=S(n)+n+1=n(n+1)/2+n+1=(n+1)[(n+1)+1]/2

所以

S ( n ) = n ∗ ( n + 1 ) / 2 S(n) = n*(n + 1) / 2 S(n)=n(n+1)/2

举例:

1、问题描述:

爬楼梯(斐波那契数列):

​ 给定一个共有 𝑛 阶的楼梯,你每步可以上 1 阶或者 2 阶,请问有多少种方案可以爬到楼顶?

2、分析:

​ 由于每轮只能上 1 阶或 2 阶,因此当我们站在第 𝑖 阶楼梯上时,上一轮只可能站在第 𝑖−1 阶或第 𝑖−2 阶上。

​ 换句话说,我们只能从第 𝑖−1 阶或第 𝑖−2 阶迈向第 𝑖 阶。

由此便可得出一个重要推论:

爬到第 𝑖−1 阶的方案数加上爬到第 𝑖−2 阶的方案数就等于爬到第 𝑖 阶的方案数

公式如下:

d p [ i ] = d p [ i − 1 ] + d p [ i − 2 ] dp[i]=dp[i-1]+dp[i-2] dp[i]=dp[i1]+dp[i2]

而其中第一阶有1种方案,第二阶楼梯有两种方案,即:

d p [ 1 ] = 1 , d p [ 2 ] = 2 dp[1]=1, dp[2]=2 dp[1]=1,dp[2]=2

3、暴力搜索

​ 这样就可以通过递归不断的将一个较大问题拆解为两个较小问题的和,直至到达最小子问题 𝑑𝑝[1] 和 𝑑𝑝[2] 时返回。

在这里插入图片描述

int climbingStairsDFS(int n) {
    // 已知 dp[1] 和 dp[2] ,返回
    if (i == 1 || i == 2)
        return i;
    int count = dfs(i - 1) + dfs(i - 2);
    return count;
}
4、动态规划

​ 观察上图 ,指数阶的时间复杂度是“重叠子问题”导致的。例如 𝑑𝑝[9] 被分解为 𝑑𝑝[8] 和 𝑑𝑝[7] ,𝑑𝑝[8] 被分解为 𝑑𝑝[7] 和 𝑑𝑝[6] ,两者都包含子问题 𝑑𝑝[7] 。

​ 以此类推,子问题中包含更小的重叠子问题。绝大部分计算资源都浪费在这些重叠的子问题上。

分析:

​ 可以发现,这个问题具有最优子结构、无后效性、重叠子问题的三个特点的,那么就可以尝试使用动态规划进行解决。

划分子问题,定义初始状态:

​ 原问题 d p [ n ] dp[n] dp[n]可以被划分为求解 d p [ n − 1 ] dp[n-1] dp[n1] d p [ n − 2 ] dp[n-2] dp[n2]的解。

​ 初始状态为 d p [ 1 ] = 1 , d p [ 2 ] = 2 dp[1]=1,dp[2]=2 dp[1]=1,dp[2]=2

确定动态规划函数(状态转移方程):

d p [ i ] = d p [ i − 1 ] + d p [ i − 2 ] dp[i]=dp[i-1]+dp[i-2] dp[i]=dp[i1]+dp[i2]

接下来填表即可:

在这里插入图片描述

int climbingStairsDP(int n) {
    if (n == 1 || n == 2)
        return n;
    // 初始化 dp 表,用于存储子问题的解
    int[] dp = new int[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];
}

动态规划案例-01背包

问题描述

​ 有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?

背包体积:8

物品编号体积(vol)价值(val)
123
234
345
456

蛮力法

​ 只需要将所有情况都考虑到,每个物品放与不放的所有组合均计算一边,然后取其中价值最大的情况即可。

现在需要采用合适的方式去表示所有的状态

​ 可以想到,数字在内存中存储形式是二进制,比如1(0000 0001),2(0000 0010),3(0000 0011)

​ 可以用数字二进制中为1的位置表示该位置的物品是否放入。

​ 这样4个物品就只需要 2 4 2^4 24这个数字表示,遍历从1到 2 4 2^4 24的所有情况即可。

public static int execute(List<Item> itemList, int maxVolume) {
  int n = itemList.size(), pow = (int) Math.pow(2, n), resultVal = 0, resultIndex = -1;
  // 遍历每一种情况
  for (int i = 1; i < pow; i++) {
    int thisVol = 0, thisVal = 0, tempIndex = i, thisIndex = 0;
    //tempIndex每次右移一位,其中右起第一位与1按位与表示这个物品是否放入
    while (tempIndex > 0) {
      if ((tempIndex & 1) == 1) {
        Item item = itemList.get(thisIndex);
        // 如果当前物品体积加上已经超出,则直接跳出此次循环
        if ((thisVol + item.getVolume()) <= maxVolume) {
          thisVal += item.getValue();
          thisVol += item.getVolume();
        } else {
          break;
        }
      }
      tempIndex = tempIndex >> 1;
      thisIndex++;
    }
    // resultVal:记录最大价值;  resultIndex:记录最大价值对应的情况
    if (thisVal > resultVal) {
      resultVal = thisVal;
      resultIndex = i;
    }
  }
  // 输出最大情况哪些物品放入
  for (int i = 0; resultIndex > 0; i++) {
    if ((resultIndex & 1) == 1) {
      System.out.println("第" + i + 1 + "个物品放入背包");
    }
    resultIndex = resultIndex >> 1;
  }
  return resultVal;
}
class Item {
    int volume;
    int value;
    public Item(int volume, int value) {
        this.volume = volume;
        this.value = value;
    }
    public int getValue() {
        return value;
    }
    public int getVolume() {
        return volume;
    }
}

动态规划

​ 分析上面蛮力法,其实可以发现不同组合之间,出现了大量的重复计算,比如:1111、0111、1011、0011都会计算0011,也就是第一个和第二个物品放入背包的情况。(1011:表示第1、2、4个物品放,第3个不放,从右往左看)

​ 这里已经出现了重复子问题,可以尝试考虑使用动态规划解决

现在看是否满足最优子结构和无后效性:

​ 这里就直接给出解释:比如第n个物品的体积是 V o l ( n ) Vol(n) Vol(n),价值为 V a l ( n ) Val(n) Val(n),且背包总体积大于物品的体积。那么对于第n个物品是否放入的最优解,应该在下面二选一:

​ 1、不放入,那么当前的最大价值就是前n-1个物品的最大价值

​ 2、放入,那么最大价值就应该是在体积 V − V o l ( n ) V-Vol(n) VVol(n)(保证当前物品能放下)情况下 n − 1 n-1 n1个物品的最大价值 + 第n个物品的价值 V a l ( n ) Val(n) Val(n)

​ 可见,这个是满足最优子结构(后面阶段的状态可以由前面阶段的状态推导出来)和无后效性(各个子问题的只与它前面的子问题的解相关)的。

根据上面的分析,我们需要记录每种体积下,前n个物品的最优解。那么可以使用一个二维数组 d p [ i , j ] dp[i, j] dp[i,j]来表示这个情况:

​ 其中i表示前i个物品,j表示体积。

​ 那么 d p [ i ] [ j ] dp[i][j] dp[i][j]就表示在体积为j的情况下,前i个物品的最优解。

定义初始状态:

​ 当i=0时,表示没有物体,那么最大价值就应是0,即 d p [ 0 ] [ j ] = 0 dp[0][ j]=0 dp[0][j]=0

​ 当j=0时,表示体积为0,那么一个物体都放不进去,那么最大价值就应是0,即 d p [ i ] [ 0 ] = 0 dp[i][0]=0 dp[i][0]=0

确定状态转移方程:

d p [ i , j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − V o l ( i ) ] ) + V a l ( i ) ) dp[i,j] = max( dp[ i-1 ][j] , dp[i-1][j-Vol(i)]) + Val(i)) dp[i,j]=max(dp[i1][j],dp[i1][jVol(i)])+Val(i))

填表:

背包体积:8

物品编号体积(vol)价值(val)
123
234
345
456

1、初始状态

i\j012345678
0000000000
10
20
30
40

2、填写前1个物品行:(第1个物品:体积为2,价值为3)

a.在体积为1时,也就是 d p [ 1 ] [ 1 ] dp[1][1] dp[1][1]

​ 此时体积为1,而第一个物品体积为2,放不下,所以 d p [ 1 ] [ 1 ] = 0 dp[1][1]=0 dp[1][1]=0

b.对于体积2~8,也就是 d p [ 1 ] [ 2 ] — d p [ 1 ] [ 8 ] dp[1][2] — dp[1][8] dp[1][2]dp[1][8]

​ 代入上面状态转移公式,得到 d p [ 1 ] [ 2 ] = 3 , d p [ 1 ] [ 3 ] = 3 , . . . , d p [ 1 ] [ 8 ] = 3 dp[1][2] =3,dp[1][3]=3,..., dp[1][8] = 3 dp[1][2]=3dp[1][3]=3,...,dp[1][8]=3

​ 也就是说,此时任意体积下,前n-1(前0个)物品的的最大价值都是0,所以最大价值就一定是第一个物品的价值。

i\j012345678
0000000000
1003333333
20
30
40

3、填写前2个物品行:(第2个物品:体积为3,价值为4)

a.在体积为为1、2时,也就是 d p [ 2 ] [ 1 ] 、 d p [ 2 ] [ 2 ] dp[2][1]、dp[2][2] dp[2][1]dp[2][2]

​ 此时体积1或2,而第2个物品体积为3,放不下,所以此时最大价值就是前n-1(1个物品)的最大价值,即 d p [ 2 ] [ 1 ] = 0 、 d p [ 2 ] [ 2 ] = 3 dp[2][1]=0、dp[2][2]=3 dp[2][1]=0dp[2][2]=3

b.在体积为3、4时,也就是 d p [ 2 ] [ 3 ] 、 d p [ 2 ] [ 4 ] dp[2][3]、dp[2][4] dp[2][3]dp[2][4]:

​ 此时体积为3或4,放得下第二个物品,带入上面状态转移公式:

​ 不放入第2个物品,则最大价值为当前体积前n-1个物品的最大价值: d p [ 2 ] [ 3 ] = 3 、 d p [ 2 ] [ 4 ] = 3 dp[2][3]=3、dp[2][4]=3 dp[2][3]=3dp[2][4]=3

​ 放入第2个物品,则最大价值为当前体积-第n个物品体积下前n-1个物品的最大价值:

d p [ 1 ] [ 0 ] + 4 = 4 、 d p [ 1 ] [ 1 ] + 4 = 4 dp[1][0]+4=4、dp[1][1]+4=4 dp[1][0]+4=4dp[1][1]+4=4

​ 4>3,所以 d p [ 2 ] [ 3 ] = 4 dp[2][3]=4 dp[2][3]=4

​ 也就是说,在体积为3的时候,此时放入第2个物品要比单独放入第1个物品价值要大

c.在体积为5~8时,也就是 d p [ 2 ] [ 5 ] — d p [ 2 ] [ 8 ] dp[2][5] — dp[2][8] dp[2][5]dp[2][8]L

​ 此时体积大于等于5,带入状态转移公式:

​ 不放入第2个物品,则最大价值为当前体积前n-1个物品的最大价值: d p [ 1 ] [ 5 — 8 ] = 3 dp[1][5—8]=3 dp[1][5—8]=3

​ 放入第2个物品,则最大价值为当前体积-第n个物品体积下前n-1个物品的最大价值: d p [ 1 ] [ 5 — 8 ] + 4 = 7 dp[1][5—8]+4=7 dp[1][5—8]+4=7

​ 7>3,所以 d p [ 2 ] [ 4 ] — d p [ 2 ] [ 8 ] = 7 dp[2][4]—dp[2][8]=7 dp[2][4]dp[2][8]=7

​ 也就是说,在体积大于等于5时,此时可以将前n-1个(第1个)和当前第n个(第2个)都装下。

i\j012345678
0000000000
1003333333
2003447777
30
40

填写前3个物品行:(第3个物品:体积为4,价值为5)

a.在体积为1、2、3时,也就是 d p [ 3 ] [ 1 — 3 ] dp[3][1—3] dp[3][1—3]

​ 此时体积小于4,放不下第3个物品,那么最大值就是前n-1个(前2个)物品的最大价值:

d p [ 3 ] [ 1 ] = 0 、 d p [ 3 ] [ 2 ] = 3 、 d p [ 3 ] [ 3 ] = 4 dp[3][1]=0、dp[3][2]=3、dp[3][3]=4 dp[3][1]=0dp[3][2]=3dp[3][3]=4

b.在体积为4时。也就是 d p [ 3 ] [ 4 ] dp[3][4] dp[3][4]

​ 此时体积等于4,可以放下第3个物品

​ 不放入第3个物品,则最大价值为当前体积前n-1个物品的最大价值: d p [ 2 ] [ 4 ] = 4 dp[2][4]=4 dp[2][4]=4

​ 放入第3个物品,则最大价值为当前体积-第n个物品体积下前n-1个物品的最大价值: d p [ 2 ] [ 0 ] + 5 = 5 dp[2][0]+5=5 dp[2][0]+5=5

​ 5>4,则 d p [ 3 ] [ 4 ] = 5 dp[3][4]=5 dp[3][4]=5

​ 也就是说,在体积为4的情况下,只放入第3个物品,要比不放入第3个物品时,前两个物品的最大价值要高。

c.在体积为5时,也就是 d p [ 3 ] [ 5 ] dp[3][5] dp[3][5]

​ 此时体积为5,放得下第3个物品

​ 不放入第3个物品,则最大价值为当前体积前n-1个物品的最大价值: d p [ 2 ] [ 5 ] = 7 dp[2][5]=7 dp[2][5]=7

​ 放入第3个物品,则最大价值为当前体积-第n个物品体积下前n-1个物品的最大价值: d p [ 2 ] [ 1 ] + 5 = 5 dp[2][1]+5=5 dp[2][1]+5=5

​ 7>5,则 d p [ 3 ] [ 5 ] = 7 dp[3][5]=7 dp[3][5]=7

​ 也就是说,在体积为5的情况下,放入第3个物品(导致前两个物品被拿出)要比前两个物品在体积为5的情况下最大价值要低。

d.在体积为6时,也就是 d p [ 3 ] [ 6 ] dp[3][6] dp[3][6]

​ 不放入第3个物品,则最大价值为当前体积前n-1个物品的最大价值: d p [ 2 ] [ 6 ] = 7 dp[2][6]=7 dp[2][6]=7

​ 放入第3个物品,则最大价值为当前体积-第n个物品体积下前n-1个物品的最大价值: d p [ 2 ] [ 2 ] + 5 = 8 dp[2][2]+5=8 dp[2][2]+5=8

​ 8>7,也就是 d p [ 3 ] [ 6 ] = 8 dp[3][6]=8 dp[3][6]=8

​ 也就是说,放入第3个物品(导致前1个物品中第2个被去掉)要比在体积为6的情况下最大价值要高

e.在体积为7、8时,也就是 d p [ 3 ] [ 7 ] 、 d p [ 3 ] [ 8 ] dp[3][7]、dp[3][8] dp[3][7]dp[3][8]

​ 不放入第3个物品,则最大价值为当前体积前n-1个物品的最大价值: d p [ 2 ] [ 7 ] = d p [ 2 ] [ 8 ] = 7 dp[2][7]=dp[2][8]=7 dp[2][7]=dp[2][8]=7

​ 放入第3个物品,则最大价值为当前体积-第n个物品体积下前n-1个物品的最大价值:

d p [ 2 ] [ 3 ] + 5 = 9 、 d p [ 2 ] [ 4 ] + 5 = 9 dp[2][3]+5=9、dp[2][4]+5=9 dp[2][3]+5=9dp[2][4]+5=9

​ 9>7, d p [ 3 ] [ 7 ] = d p [ 3 ] [ 8 ] = 9 dp[3][7]=dp[3][8]=9 dp[3][7]=dp[3][8]=9

​ 也就是说,在体积为7、8时,放入第3个物品(导致前2个物品中第1个被去掉)要比不放入第3个前两个物品最大价值要高

i\j012345678
0000000000
1003333333
2003447777
3003457899
40

填写前4个物品行:

​ 过程与上面类似

i\j012345678
0000000000
1003333333
2003447777
3003457899
40034578910

​ 最终,得到在体积为8的情况下,4个物品的最优解为 d p [ 4 ] [ 8 ] = 10 dp[4][8]=10 dp[4][8]=10

代码:

/**
* 使用动态规划获得最大的价值
*
* @param itemList  物品
* @param maxVolume 背包最大体积
* @return 最大价值
*/
public static int execute(List<Item> itemList, int maxVolume) {
  // 初始化dp表,第一列初始赋值为0(体积为0什么都放不下),第一行初始赋值为0(没有物品默认为0)。
  int[][] dpTable = new int[itemList.size() + 1][maxVolume + 1];
  int[][] dpTableTrance = new int[itemList.size() + 1][maxVolume + 1];

  // 填表
  for (int i = 1; i < itemList.size() + 1; i++) {
    for (int j = 1; j < maxVolume + 1; j++) {
      // 当前背包体积 < 当前物品体积,即放不下。
      // itemList.get(i - 1) 是因为物品List从下标0开始,不是从1开始
      if (j < itemList.get(i - 1).getVolume()) {
        // 放不下当前物品,那么当前情况下最大价值为 前i-1个物品的在该体积下的最大价值
        dpTable[i][j] = dpTable[i - 1][j];
      } else {
        // 当前背包体积 > 当前物品体积,可以放得下
        // 当前容量下,只有两个选择,放入当前物品,不放入当前物品
        //      不放入当前物品:最大价值为当前体积下前i-1个物品的最大值
        //      放入当前物品:最大价值为前i-1个物品在背包体积为(当前体积-当前物品体积)的最大值
        dpTable[i][j] = Math.max(dpTable[i - 1][j],
                                 dpTable[i - 1][j - itemList.get(i - 1).getVolume()] + itemList.get(i - 1).getValue());
      }
    }
  }
  return dpTable[itemList.size()][maxVolume];
}

class Item {
  int volume;
  int value;
  public Item(int volume, int value) {
    this.volume = volume;
    this.value = value;
  }
  public int getValue() {
    return value;
  }
  public int getVolume() {
    return volume;
  }

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

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

相关文章

区别五大数据可视化工具,有这一篇就够了

进入企业数字化时代&#xff0c;数据可视化工具的重要性被越来越多企业看到。这些企业都希望在短时间内找到适合自己的数据可视化工具。以下是针对帆软BI、奥威BI、思迈特BI&#xff08;Smartbi&#xff09;、永洪BI和亿信华辰BI的详细介绍&#xff0c;希望能帮助用户企业快速筛…

大语言模型 (LLM) 红队测试:提前解决模型漏洞

大型语言模型 (LLM) 的兴起具有变革性&#xff0c;以其在自然语言处理和生成方面具有与人类相似的卓越能力&#xff0c;展现出巨大的潜力。然而&#xff0c;LLM 也被发现存在偏见、提供错误信息或幻觉、生成有害内容&#xff0c;甚至进行欺骗行为的情况。一些备受关注的事件包括…

FL Studio 21.2.2.3914 Win绿色版内置破解补丁和汉化文件,可以完美激活软件

Image-Line FL Studio 21.2.2 x64是一款极受欢迎的音乐制作软件&#xff0c;被广泛用于专业的音乐制作和音频编辑。作为FL Studio系列的最新版本&#xff0c;它在音乐制作界中因其强大的功能、灵活的工作流程和用户友好的界面而备受推崇。 PS.本次为你带来的是fl studio21破解版…

短视频压缩与编码技术在短剧APP小程序开发中的应用:技术选择与工具推荐

在短剧APP小程序开发中&#xff0c;选择合适的短视频压缩与编码技术及工具对于实现高效的视频处理至关重要。本文将探讨如何选择合适的技术和工具&#xff0c;以及推荐一些在实际开发中常用的解决方案。 技术选择的原则 平衡压缩率与视频质量&#xff1a;在选择压缩技术时&…

基于云效 AppStack,5 分钟搞定一个 AI 应用的开发和部署

实验介绍 区别于传统的流水线工具&#xff0c;本实验将带你体验云效应用交付平台 AppStack&#xff0c;从应用视角&#xff0c;完成一个 AI 聊天应用的高效交付。 你将体验到&#xff1a; 基于应用模板快速初始化应用&#xff0c;包含应用的代码库、部署编排架构、变量组、环…

京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设

京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设 京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设 水库大坝监测系统主要包括渗流监测系统、流量监测系统、雨量监测系统、沉降监测系统组成。每一个监测系统由监测仪器及自动化数据采集装置&#xff08;内置通信装…

virtualbox扩展磁盘

使用virtualbox搭建虚拟机&#xff0c;如果磁盘不够用了&#xff0c;可以通过以下方式扩展。 扩容磁盘 分区扩展 查看磁盘情况 fdisk -l Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors Units sectors of 1 * 512 512 bytes Sector size (logical/phys…

HAL库--内存保护(MPU)实验

MPU是内核外设&#xff0c;想获取相关资料只能从内核手册查找 MPU功能仅F7/H7系列具备 内存保护单元(MPU介绍) MPU基本介绍 说白了MPU用来管理内存和外设存储区的访问权限 MPU可配置保护8/16个内存区域(看芯片型号)&#xff0c;每个区域最小要求256字节&#xff0c;且每个区…

【启明智显分享】个位数价格工业HMI芯片:720P@60fps,配备2D加速

我们生活在一个“屏”的时代&#xff0c;工业自动化、智能生活的实现都离不开屏幕的帮助&#xff0c;而对于消费者而言&#xff0c;最大的痛点就是显示屏的画质&#xff0c;一个优质的人机交互界面影响着用户体验&#xff0c;流畅清晰的图像呈现与屏幕的分辨率、刷新率都息息相…

Spring-Cloud-Gateway--源码分析及应用

文章目录 一、简介1.1 术语 1.3 特性1.4 Spring Cloud Gateway与Spring Cloud ZuulSpring Cloud ZuulWebflux模型 1.5 如何集成Gateway 二、工作原理2.2 Gateway类图 三、配置路由谓词工厂和网关过滤工厂3.1 两种不同的配置路由方式通过yml文件来配置通过Java Bean来配置 3.2 R…

vue生命周期及组件讲解(如何导入引用外部vue文件,以及注册全局变量,自定义标签效果)

生命周期钩子的理解与应用 函数说明onBeforeMount( )组件挂载前onMounted( )组件挂载后onBeforeUpdate( )组件更新前onUpdated( )组件中任意的DOM元素更新后onBeforeUnmount( )组件实例被销毁前onUnmounted( )组件实例被销毁后 生命周期在 各类应用以及网站中使用非常广泛&…

Running Gradle task ‘assembleDebug‘ Flutter项目

基于Android方面运行Flutter项目一直卡在 Launching lib\main.dart on Android SDK built for x86 in debug mode… Running Gradle task ‘assembleDebug’… 基础原因&#xff1a; 默认存放Gradle插件包的Maven仓库是国外(需VPN) 我的原因&#xff1a; 缺少JDK和缺少Androi…

Python 俄罗斯方块小游戏【含Python源码 MX_007期】

系统简介&#xff1a; 俄罗斯方块是一款经典的俄罗斯益智游戏&#xff0c;由苏联工程师阿列克谢帕基特诺夫&#xff08;Alexey Pajitnov&#xff09;于1984年创建。在游戏中&#xff0c;玩家需要操纵不同形状的方块&#xff0c;以水平移动和旋转的方式&#xff0c;使它们在屏幕…

【论文阅读】-- 时态合并树状图:时态标量数据的基于拓扑的静态可视化

时态合并树状图&#xff1a;时态标量数据的基于拓扑的静态可视化 摘要1 引言2 相关工作及背景介绍2.1 增广合并树2.2 (增强)合并树的可视化与跟踪2.3 特征跟踪2.4 数据线性化 3 时间合并树状图3.1 映射单个时间步长&#xff1a; R d → R R^d \rightarrow R Rd→R3.2 映射所有时…

Stable Diffusion: ControlNet 插件安装

前面介绍了一些通过代码实现ControlNet进行控制的案例。现在通过Stable Diffusion体验一下更便捷的操作。 Stable Diffusion插件安装办法大致相同。启动Stable Diffusion后&#xff0c;点击最右边的“扩展”&#xff0c;点击“可下载”&#xff0c;点击“加载扩展列表”。 视网…

开个技术外挂 | 数字孪生技术如何成为美洲杯帆船赛成功的关键?

若您对数据分析以及人工智能感兴趣&#xff0c;欢迎与我们一起站在全球视野关注人工智能的发展&#xff0c;与Forrester 、德勤、麦肯锡等全球知名企业共探AI如何加速工业变革&#xff0c;共享众多优秀行业案例&#xff0c;开启AI人工智能全球新视野&#xff01;&#xff01; …

【小白专用 已验证24.6.7】C# MySQL数据库访问操作封装类

一、底层库介绍 本文主要介绍数据库访问操作类&#xff0c;包含&#xff1a;SQL插入脚本、SQL查询脚本、数据库表是否存在判断、带参脚本执行、包含事务回滚脚本执行、存储过程脚本等等。 特殊说明 在使用之前&#xff0c;先安装 MySql.Data 插件 二、底层库源码 2.1 程序源…

如何合并pdf文件到一个pdf

在现代办公和学习中&#xff0c;PDF格式的文件因其跨平台兼容性和安全性得到了广泛应用。然而&#xff0c;有时我们需要将多个PDF文件合并成一个&#xff0c;以便于管理和分享。本文将详细介绍几种合并PDF的方法&#xff0c;帮助读者轻松完成PDF文件的合并工作。 首先通过浏览器…

JWT工具【工具类】

一、JWT JSON Web Token (JWT)是一个开放标准&#xff08;RFC 7519&#xff09;&#xff0c;定义了一种紧凑且自包含的方式&#xff0c;以JSON对象的形式在各方之间安全地传输信息。这种信息可以被验证和信任&#xff0c;因为它是数字签名的。具体来说&#xff0c;JWT是一种用…

柏曼的台灯值得入手吗?书客、明基横向测评对比

据相关研究显示&#xff0c;我国青少年的近视问题尤为严峻&#xff0c;总体近视率已逼近53%&#xff0c;这一超过半数的数据令人触目惊心。随着孩子学龄的增长&#xff0c;学习负担不断加重&#xff0c;眼部的压力也随之剧增&#xff0c;从而导致近视率持续攀升。普通台灯可能发…