【代码随想录】【动态规划】背包问题 - 完全背包

完全背包

模板:完全背包问题

问题描述

完全背包问题与01背包问题唯一的区别在于:

  • 在01背包中:每个物品只有一个,要么放入背包,要么不放入背包
  • 在完全背包中:每个物品有无限多个,可以不放入背包,也可以多次放入背包

解法一:二维dp

(加粗部分是和01背包中有区别的部分)

dp[i][j]:将下标小于等于 i 的物品放入容量为 j 的背包中所能取得的最大价值

在计算dp[i][j]时:对于下标为 i 的物品进行讨论:

  • 如果放不下物品 i(当前背包容量小于物品 i 的体积,j < v[i]):dp[i][j] = dp[i-1][j] ,即将下标小于等于 i-1 的物品放入容量为 j 的背包中所能取得的最大价值
  • 如果能放下物品 i(j >= v[i]):
    • 有两种选择:
      • 不放入物品 i :dp[i][j] = dp[i-1][j]
      • 放入物品 i :dp[i][j] = w[i] + dp[i][j-v[i]] 在本次放入物品i之前背包中可以已经有物品i了
    • 从二者中选择能取得的最大价值更大的一个:dp[i][j] = max{dp[i-1][j], w[i] + dp[i][j-v[i]]}

递推公式
d p [ i ] [ j ] = { j < v [ i ] : d p [ i − 1 ] [ j ] j ≥ v [ i ] : max ⁡ ( d p [ i − 1 ] [ j ] , w [ i ] + d p [ i ] [ j − v [ i ] ] ) dp[i][j] = \left\{\begin{matrix} j < v[i]: & dp[i-1][j]\\ j \ge v[i]: & \max (dp[i-1][j], w[i] + dp[i][j-v[i]]) \end{matrix}\right. dp[i][j]={j<v[i]:jv[i]:dp[i1][j]max(dp[i1][j],w[i]+dp[i][jv[i]])

计算顺序
在计算dp[i][j]时可能会用到dp[i-1][j]位置和dp[i][0…j-1]位置的值,在计算dp[i][j]之前要保证这些位置的值已经计算过了。

在这里插入图片描述

下面几种计算顺序都可以实现这一目标:

  • 外循环遍历物品,内循环遍历背包容量 / 一行一行计算
    • 每一行从左向右计算
  • 外循环遍历背包容量,内循环遍历物品 / 一列一列计算
    • 每一列从上向下计算

在计算每一行时必须按照从左向右的顺序计算,因为计算dp[i][j]时会用到本行该位置之前的数据(dp[i][0…j-1])。

但是在计算每一列时必须按照从上向下的顺序计算,因为计算dp[i][j]时会用到本行该位置之前的数据(dp[i-1][j])。

初始化
不同的计算顺序需要初始化的内容有所不同:

  • 外循环遍历物品,内循环遍历背包容量 / 一行一行计算:既需要初始化第一行,又需要初始化第一列
  • 外循环遍历背包容量,内循环遍历物品 / 一列一列计算:既需要初始化第一行,又需要初始化第一列

具体来说:

  • 对第一行的初始化:i=0, j=0->V
    • dp[0][j]:在容量为j的背包中放物品0
      • j < v[0]:放不下,dp[0][j] = 0
      • j >= v[0]:能放下,dp[0][j] = w[0]
  • 对第一列的初始化:i=0->n-1, j=0
    • dp[i][0]:在容量为0的背包中放物品,dp[i][0] = 0
public int packageComplete(){// dp[i][j]: 将下标小于等于 i 的物品放入容量为 j 的背包中所能取得的最大价值int[][] dp = new int[n][V+1];// 初始化第一行: dp[0][0...j]for(int j = 0; j <= V; j++){// dp[0][j]:在容量为j的背包中放物品0if(j < v[0]){dp[0][j] = 0;    // 放不下物品0}else{// 能放下物品0dp[0][j] = dp[0][j-v[0]] + w[0]; }}// 初始化第一列:dp[0...n][0]for(int i = 0; i < n; i++){// 在容量为0的背包里放物品,最大价值必然为0dp[i][0] = 0;}// 递推计算: 外循环遍历物品,内循环遍历背包容量for(int i = 1; i < n; i++){for(int j = 0; j <= V; j++){if(j < v[i]){// 放不下物品idp[i][j] = dp[i-1][j];}else{// 能放下物品idp[i][j] = Math.max(dp[i-1][j],             // 不放入物品iw[i] + dp[i][j-v[i]]    // 放入物品i(此时背包中可以已有物品i));}}}// 返回结果return dp[n-1][V];
}

解法二:一维dp / 滚动数组

观察二维dp的递推公式发现:在计算dp[i][j]时会用到前一行的第j个数据,和当前行的前j-1个数据
d p [ i ] [ j ] = { j < v [ i ] : d p [ i − 1 ] [ j ] j ≥ v [ i ] : max ⁡ ( d p [ i − 1 ] [ j ] , w [ i ] + d p [ i ] [ j − v [ i ] ] ) dp[i][j] = \left\{\begin{matrix} j < v[i]: & dp[i-1][j]\\ j \ge v[i]: & \max (dp[i-1][j], w[i] + dp[i][j-v[i]]) \end{matrix}\right. dp[i][j]={j<v[i]:jv[i]:dp[i1][j]max(dp[i1][j],w[i]+dp[i][jv[i]])

如果我们按照 “一行一行计算,每一行从左往右计算” 的顺序进行二维dp的计算:

...
在计算dp[i][j-1]时会用到dp[i-1][j-1]和dp[i][0], dp[i][1]...dp[i][j-2]
在计算dp[i][j]  时会用到dp[i-1][j]  和dp[i][0], dp[i][1]...dp[i][j-2], dp[i][j-1]
在计算dp[i][j+1]时会用到dp[i-1][j+1]和dp[i][0], dp[i][1]...dp[i][j-2], dp[i][j-1], dp[i][j]
...

观察发现,在计算完dp[i][j]之后,就再也用不到dp[i-1][j]

综上所述,我们可以只用一行(即一个长度为V+1的数组)作为dp数组,滚动存储每一行的计算结果,不再需要的数据被新计算的结果覆盖使用。

  • 一开始先将该数组的内容初始化为原二维dp的第一行的内容
  • 在计算原二维dp的第 i 行( 2 ≤ i < n 2 \leq i < n 2i<n)时:
    • 计算开始前:滚动数组中正好是原二维dp第 i-1 行的内容
    • 从左向右计算for(int j=0; j<=V; j++)
    • 递推公式修改为: d p [ j ] = { j < v [ i ] : d p [ j ] j ≥ v [ i ] : max ⁡ ( d p [ j ] , w [ i ] + d p [ j − v [ i ] ] ) dp[j] = \left\{\begin{matrix} j < v[i]: & dp[j]\\ j \ge v[i]: & \max (dp[j], w[i] + dp[j-v[i]]) \end{matrix}\right. dp[j]={j<v[i]:jv[i]:dp[j]max(dp[j],w[i]+dp[jv[i]])
    • 由递推公式计算出的 dp[j] 实际上就是原二维dp中的 dp[i][j],而此时滚动数组中下标为 j 的位置存放的是 dp[i-1][j],这个数值在之后的计算中都用不到了,因此将其覆盖用于存储 dp[i][j]。
public int package01(){// dp[j]: 将物品放入容量为 j 的背包中所能取得的最大价值int[] dp = new int[V+1];// 初始化第一行: 在容量为j的背包中放物品0for(int j = 0; j <= V; j++){if(j < v[0]){dp[j] = 0;    // 放不下物品0}else{// 能放下物品0dp[j] = dp[j-v[0]] + w[0]; }}// 递推计算: 外循环遍历物品,内循环遍历背包容量for(int i = 1; i < n; i++){// 原二维dp中的第一列数据,每行遇到时再初始化dp[0] = 0;// 计算这一行的剩余数据for(int j = 1; j <= V; j++){// if(j < v[i]){//     // 放不下物品i//     dp[j] = d[j]; // 什么也没做// }else{//     // 能放下物品i//     dp[j] = Math.max(//         dp[j],               // 不放入物品i//         w[i] + dp[j-v[i]]    // 放入物品i(此时背包中可以已有物品i)//     );// }if(j >= v[i]){dp[j] = Math.max(dp[j], w[i] + dp[j-v[i]]);}}}// 返回结果return dp[V];
}

518. 零钱兑换 Ⅱ

需要注意当总金额j = 0时,认为只有一种组合方式:什么也不选。

代码实现:二维dp

class Solution {public int change(int amount, int[] coins) {int n = coins.length;// dp[i][j]: 从下标小于i的硬币面额中选择,恰好凑够总金额j的组合数int dp[][] = new int[n][amount+1];// 初始化第一行:只用面额为coins[0]的硬币来凑dp[0][0] = 1; // 总金额为0时只有一种组合方式:什么也不选for(int j = 1; j <= amount; j++) {if(j < coins[0]){// 总金额j小于coins[0] => 不能凑成总金额jdp[0][j] = 0;}else{// 总金额j大于等于coins[0] => 如果减去当前面额后的总金额j-coins[0]不能正好凑齐,那么总金额j也无法正好凑齐;否则,先凑够j-coins[0]后再加上当前硬币面额即可,总组合数等于dp[0][j-coins[0]]dp[0][j] = (dp[0][j-coins[0]] == 0 ? 0 : dp[0][j-coins[0]]);}}// 初始化第一列:凑成总金额0 => 只有一种组合方式:什么也不选// dp[0][0]已经在前面初始化过了for(int i = 1; i < n; i++){dp[i][0] = 1;}// 递推计算for(int i = 1; i < n; i++){for(int j = 1; j <= amount; j++){if(j < coins[i]){// 总金额j小于coins[i] => 不能选择coins[i]dp[i][j] = dp[i-1][j];}else{// 总金额j大于等于coins[i] => 可以选择coins[i],也可以不选择coins[i],两种加起来为总组合数dp[i][j] = dp[i-1][j] + (dp[i][j-coins[i]] == 0 ? 0 : dp[i][j-coins[i]]);}}}// 返回结果return dp[n-1][amount];}
}

代码实现:一维dp

class Solution {public int change(int amount, int[] coins) {int n = coins.length;// dp[j]: 恰好凑够总金额j的组合数int dp[] = new int[amount+1];// 初始化第一行:只用面额为coins[0]的硬币来凑dp[0] = 1; // 总金额为0时只有一种组合方式:什么也不选for(int j = 1; j <= amount; j++) {if(j < coins[0]){// 总金额j小于coins[0] => 不能凑成总金额jdp[j] = 0;}else{// 总金额j大于等于coins[0] => 如果减去当前面额后的总金额j-coins[0]不能正好凑齐,那么总金额j也无法正好凑齐;否则,先凑够j-coins[0]后再加上当前硬币面额即可,总组合数等于dp[j-coins[0]]dp[j] = (dp[j-coins[0]] == 0 ? 0 : dp[j-coins[0]]);}}// 递推计算for(int i = 1; i < n; i++){dp[0] = 1; // 初始化原二维dp中的第一列for(int j = 1; j <= amount; j++){// if(j < coins[i]){//     // 总金额j小于coins[i] => 不能选择coins[i]//     dp[j] = dp[j]; // 什么也没做// }else{//     // 总金额j大于等于coins[i] => 可以选择coins[i],也可以不选择coins[i],两种加起来为总组合数//     dp[j] = dp[j] + (dp[j-coins[i]] == 0 ? 0 : dp[j-coins[i]]);// }if(j >= coins[i]){dp[j] = dp[j] + (dp[j-coins[i]] == 0 ? 0 : dp[j-coins[i]]);}}}// 返回结果return dp[amount];}
}

377. 组合总和 Ⅳ

我觉得这道题实际上是爬楼梯的进阶版,不属于完全背包问题。

因为这道题中是要考虑选择的顺序的,(2, 1, 1)(1, 1, 2)就是两个不同的可行解;而背包问题是不考虑顺序的,在背包问题中认为先选择1还是先选择2都是一样的,比如上一道题518. 零钱兑换 Ⅱ就是一个典型的完全背包问题。

而在爬楼梯问题中,把整个过程看作是一系列的决策过程,而在计算dp[i]时主要考虑的是:在本轮有哪几种选择?

对应到该问题中,就是:将整个过程看作是从nums数组中依次选择数字的过程,每次只能选一个数字,数字可以重复且考虑顺序,问选出的一组数字的总和正好为target的取数方式有几种?

  • dp[i]:从nums中每次选择一个数字(可以重复,考虑顺序),使得总和为i,共有几种选择
  • 在计算dp[i]时:考虑在本轮有哪几种选择?(n种)
    • 共n种选择,对于每一个nums[j],(0<=j<n):如果nums[j] <= i,则可以先选出总和为i-nums[j]的一组数,然后在本轮选择nums[j]
    • 对所有情况求和得到本轮的总选择数
  • 递推公式 d p [ i ] = ∑ j = 0 n − 1 { n u m s [ j ] < = i : d p [ j − d p [ i ] ] n u m s [ j ] > i : 0 } dp[i]=\sum_{j=0}^{n-1} {\begin{Bmatrix} nums[j] <= i: & dp[j-dp[i]]\\ nums[j] > i: & 0 \end{Bmatrix}} dp[i]=j=0n1{nums[j]<=i:nums[j]>i:dp[jdp[i]]0}
  • 计算顺序:在计算dp[i]时可能会用到dp[0...i-1],因此从前向后计算(i = 0 -> target)即可
  • 初始化dp[0]的含义是 “从nums中每次选择一个数字(可以重复,考虑顺序),使得总和为0,共有几种选择”,答案是只有一种选择——什么也不选,因此dp[0] = 1;
class Solution {public int combinationSum4(int[] nums, int target) {int n = nums.length;// dp[i]: 从nums中每次选择一个数字(可以重复,考虑顺序),使得总和为i,共有几种选择int[] dp = new int[target+1];// 初始化: 总和为0只有1种选择 => 什么也不选dp[0] = 1; // 递推计算for(int i = 1; i <= target; i++){dp[i] = 0;for(int j = 0; j < n; j++){dp[i] += (nums[j] <= i ? dp[i-nums[j]] : 0);}}// 返回结果return dp[target];}
}

322. 零钱兑换

如果用-1来表示不能凑成总金额,会导致dp[]数组中元素的含义不统一,正好题目又要求要求最小值,这样的话在讨论的时候需要对-1的情况进行单独讨论,逻辑有点啰嗦。

代码实现

class Solution {public int coinChange(int[] coins, int amount) {int n = coins.length;// dp[i][j]: 从下标小于i的硬币面额中选择,恰好凑够总金额j所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,则为-1 。int[][] dp = new int[n][amount+1];// 初始化第一行:用面额为coins[0]的硬币凑成总金额jdp[0][0] = 0; // 总金额为0时只有一种组合方式:什么也不选,此时所需的最小硬币数为0for(int j = 1; j <= amount; j++){if(j < coins[0]){// 总金额j小于coins[0] => 不能凑成总金额jdp[0][j] = -1;}else{// 总金额j大于等于coins[0] => 如果减去当前面额后的总金额j-coins[0]不能正好凑齐,那么总金额j也无法正好凑齐;否则,先凑够j-coins[0]后再加上当前硬币面额即可,所需的最少硬币数等于dp[0][j-coins[0]]+1dp[0][j] = (dp[0][j-coins[0]] == -1 ? -1 : dp[0][j-coins[0]]+1);}} // 初始化第一列:凑成总金额0 => 只有一种组合方式:什么也不选,此时所需的最小硬币数为0// dp[0][0]已经在前面初始化过了for(int i = 1; i < n; i++){dp[i][0] = 0;}// 递推计算for(int i = 1; i < n; i++){for(int j = 1; j <= amount; j++){if(j < coins[i]){// 总金额j小于coins[i] => 不能选择coins[i],问题转换为dp[i-1][j]dp[i][j] = dp[i-1][j];}else{// 总金额j大于等于coins[i] => 可以选择coins[i],也可以不选择coins[i],两者取最小// 由于-1具有特殊含义且题目要求是取最小值,此时需要进行分类讨论if(dp[i-1][j] == -1 && dp[i][j-coins[i]] == -1){dp[i][j] = -1; // 如果两种都不能恰好凑成}else if(dp[i-1][j] == -1){// dp[i-1][j] == -1, dp[i][j-coins[i]] != -1dp[i][j] = dp[i][j-coins[i]] + 1;}else if(dp[i][j-coins[i]] == -1){// dp[i-1][j] != -1, dp[i][j-coins[i]] == -1dp[i][j] = dp[i-1][j];}else{dp[i][j] = Math.min(dp[i-1][j], dp[i][j-coins[i]] + 1);}}}}// 返回结果return dp[n-1][amount];}
}

反思总结

受到前面377. 组合总和 Ⅳ的启发,我发现其实背包问题在先遍历背包容量再遍历物品的计算顺序下的一维dp优化解法就是按照 “把整个过程看作是一系列的决策过程,而在计算dp[i]时主要考虑的是在本轮如何进行决策” 的思路(这是解决动态规划问题的基本思路——多阶段决策)进行的,按照这一思路直接去思考会直观的多!因此接下来我将尝试按照这种思路来解决问题,第二轮刷题时再统一进行整理。

279. 完全平方数

该问题可以转换为完全背包问题:

  • 共有 ⌊ n ⌋ \left \lfloor \sqrt{n} \right \rfloor n 个物品, 1 ≤ n ≤ ⌊ n ⌋ 1 \leq n \leq \left \lfloor \sqrt{n} \right \rfloor 1nn ,其中第i个物品的重量为 i 2 i^2 i2
  • 背包的最大容量为 n n n
  • 求能使背包恰好装满的最少物品数量

思路二:多阶段决策

dp[i]: 总和为i的完全平方数的最少数量,即背包最大容量为i时使背包恰好装满的最少物品数量。

将这一过程看作一个多阶段决策过程,在每一次决策时,即计算每一个dp[i]时,从所有物品中选择一个装入背包中。
具体来说,计算dp[i]时,即背包最大容量为i时:

  • 有那些选择? 背包能装下的物品下标集合为: { k ∣ 1 ≤ k 2 ≤ i } \{ k | 1\leq k^2 \leq i \} {k∣1k2i}
    • 如果在本轮决策中选择装入物品k,需要先在之前的决策中向背包装入重量为 i − k 2 i-k^2 ik2 的物品。此时使得背包恰好装满时的最少物品数量等于: d p [ i ] = d p [ i − k 2 ] + 1 dp[i] = dp[i-k^2]+1 dp[i]=dp[ik2]+1
  • 如何做决策? 选择装入背包后,使【使得背包恰好装满时的最少物品数量】最少的那一个,其实就是对所有决策结果取最小值
class Solution {public int numSquares(int n) {// dp[i]: 总和为i的完全平方数的最少数量,即背包最大容量为i时使背包恰好装满的最少物品数量。 int[] dp = new int[n+1];// 初始化dp[0] = 0;// 递推计算for(int i = 1; i <= n; i++){int min = Integer.MAX_VALUE;for(int k = 1; k*k <= i; k++){min = Math.min(min, dp[i-k*k] + 1);}dp[i] = min;}// 返回结果return dp[n];}
}

139. 单词拆分

该问题问能否用字典worddict中的单词拼出字符串s

可以转换为下面这个问题:

  • 有一个字符串集合worddict
  • 依次从该字符串集合中选出一系列字符串,每个字符串可以选多次(类似于有放回抽取),将这些字符串按顺序拼接
  • 问能否正好拼出字符串s

由于该问题需要考虑顺序,所以只能按照多阶段决策的思路来思考。

dp[i]:问能否用字典worddict中的单词拼出【字符串s的前i个字符组成的前缀字符串】

在每一次决策中,即在计算dp[i]时:

  • 有哪些选择? 可以选择的单词的下标集合: { k ∣ 单词 w o r d d i c t [ k ] 正好是 d p [ i ] 的后缀子字符串 } \{ k | 单词worddict[k]正好是dp[i]的后缀子字符串 \} {k单词worddict[k]正好是dp[i]的后缀子字符串}
    • 如果在本轮决策中选择单词worddict[k],则能否拼出字符串s取决于dp[i-worddict[k].length]
  • 如何做决策?
    • 如果在本轮有某一个选择能够拼出字符串s,本轮的决策结果就为true,其实就是对所有选择的结果做或运算
class Solution {public boolean wordBreak(String s, List<String> wordDict) {// dp[i]: 问能否用字典worddict中的单词拼出字符串s的前i个字符组成的前缀字符串boolean[] dp = new boolean[s.length()+1];// 初始化dp[0] = true; // 在字典中什么都不选时,正好拼出空字符串// 递推计算for(int i = 1; i <= s.length(); i++){String curStr = s.substring(0, i);for(String word : wordDict){dp[i] = false;if(curStr.endsWith(word) && dp[i-word.length()]){dp[i] = true;break;}}}// 返回结果return dp[s.length()];}
}

碎碎念:事实证明直接用多阶段决策的思路做就OK!

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

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

相关文章

卓豪Zoho CRM怎么收费?多少钱一年?

卓豪Zoho CRM作为一款功能强大且高度可定制的企业级客户关系管理系统&#xff0c;其收费标准因版本不同而有所差异&#xff0c;旨在满足不同规模及需求的企业。Zoho CRM提供多种套餐选择&#xff0c;包括但不限于免费版、标准版、专业版、企业版以及旗舰版。每种版本都包含了核…

基于Springboot的大学生平时成绩量化管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的大学生平时成绩量化管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三…

娱乐营销的新玩法:Kompas.ai如何让内容更加趣味化

在数字化时代&#xff0c;内容营销已成为品牌与消费者沟通的重要桥梁。然而&#xff0c;随着信息的爆炸式增长&#xff0c;用户的注意力越来越分散&#xff0c;传统的营销方式已经难以吸引用户的兴趣。在这种背景下&#xff0c;娱乐营销应运而生&#xff0c;它通过将娱乐元素融…

华东政法大学公布2024《负面清单期刊目录》,附目录

近日&#xff0c;华东政法大学公布2024《负面清单期刊目录》&#xff0c;包括《齐齐哈尔大学学报(哲学社会科学版)》《景德镇学院学报(社科)》《九江学院学报(社科)》《北京印刷学院学报》《江西电力职业技术学院学报》《中国多媒体与网络教学学报》《吉林省教育学院学报》《开…

Poetry Camera照相机将照片转换成诗歌并打印出来;吴恩达新课程深入了解Mistral;科学研究AI小助手data-to-paper

✨ 1: Poetry Camera 将拍摄的照片转换成诗歌并打印出来 Poetry Camera——一个能够把它所见之物转化成诗歌并打印出来的相机。你在一个美丽的公园&#xff0c;或者是一个充满故事的老街道。只要用Poetry Camera拍下这一刻&#xff0c;它就能立刻给你一首关于这个场景的诗。 …

【JAVA进阶篇教学】第十五篇:Java中AQS讲解

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第十五篇&#xff1a;Java中AQS讲解。 在Java并发编程中&#xff0c;AQS&#xff08;AbstractQueuedSynchronizer&#xff09;是一个重要的框架&#xff0c;用于实现同步器和锁的基础。它提供了一种灵活的方式来实现各种…

浏览器不兼容 replaceAll 方法问题解决

问题 在一些较旧版本的浏览器中可能会出现 replaceAll 方法不兼容&#xff0c;提示replaceAll 方法 undefined 的问题。浏览器版本兼容情况如下图所示&#xff1a; 解决 可以通过 replace 正则表达式 的方法来代替 replaceAll 方法&#xff1a; let str "我是一段文本…

CorelDRAW2024设计新境界,等你解锁!

CorelDRAW&#xff0c;这款由加拿大Corel公司开发的平面设计软件&#xff0c;自从1989年问世以来&#xff0c;就以其强大的功能和用户友好的界面&#xff0c;在全球设计师中享有极高的声誉。今天&#xff0c;我们要聊的主角是它的最新版本——CorelDRAW 2024。 CDR永久版安装包…

材料物理 笔记-8

原内容请参考哈尔滨工业大学何飞教授&#xff1a;https://www.bilibili.com/video/BV18b4y1Y7wd/?p12&spm_id_frompageDriver&vd_source61654d4a6e8d7941436149dd99026962 或《材料物理性能及其在材料研究中的应用》&#xff08;哈尔滨工业大学出版社&#xff09; ——…

出租车计价器设计与实现(论文 + 源码)

关于java出租车计价器设计与实现.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89304164 出租车计价器设计与实现 摘 要 在我国&#xff0c;出租车行业是八十年代初兴起的一项新兴行业&#xff0c;随着出租车的产生&#xff0c;计价器也就应运而生。但当时在全…

【异常】SpringBoot整合RabbitMQ-发送消息报错

错误信息 reply-code406, reply-textPRECONDITION_FAILED - inequivalent arg ‘x-message-ttl’ for queue ‘hello-queue’ in vhost ‘/lq’: received none but current is the value ‘10000’ of type ‘signedint’, class-id50, method-id10 错误原因 hello-queue这…

日志的基本用法

目标 1. 掌握如何设置日志级别 2. 掌握如何设置日志格式 3. 掌握如何将日志信息输出到文件中 1. logging模块 Python中有一个标准库模块logging可以直接记录日志 1.1 基本用法 import logging logging.debug("这是一条调试信息") logging.info("这是一条…

迪安诊断数智中心战略与PMO负责人徐黎明受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 迪安诊断技术集团股份有限公司数智中心战略与PMO负责人徐黎明先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“软件研发项目管理指标体系建设实践”。大会将于6月29-30日在北京举办&#xff0c;敬请关注&#xff01; …

01-项目功能,架构设计介绍

稻草快速开发平台 开发背景就是通过此项目介绍使用SpringBoot Vue3两大技术栈开发一个拥有动态权限、路由的前后端分离项目&#xff0c;此项目可以继续完善&#xff0c;成为一个模板为将来快速开发做铺垫。 实现功能 开发流程 通过命令构建前端项目在VSCode中开发&#xff…

【话题】Agent AI智能体的未来

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景一、Agent AI智能体的角色二、Agent AI智能体的发展路径三、Agent AI智能体可能带来的挑战文章推荐 背景 随着Agent AI智能体的智能化水平不断提高&#xff0c;它们…

Llama3中文聊天项目全能资源库

Llama3 中文聊天项目综合资源库&#xff0c;集合了与Lama3 模型相关的各种中文资料&#xff0c;包括微调版本、有趣的权重、训练、推理、评测和部署的教程视频与文档。1. 多版本支持与创新&#xff1a;该仓库提供了多个版本的Lama3 模型&#xff0c;包括基于不同技术和偏好的微…

STK12 RPO模块学习(2)

一、Coast RPO Sequence 这个序列运行卫星直到它达到了下面三个条件之一。 1&#xff09;截至时间。2)圈数到达了限制。3&#xff09;其他条件&#xff0c;比如近地点。 默认情况下&#xff0c;Astrogator使用“Earth HPOP Default v10”预报器。你能够修改呈其他修改器。下…

【Linux线程(一)】线程初理解

前言&#xff1a; &#xff08;一&#xff09;线程的概念 &#xff08;二&#xff09;线程的理解 &#xff08;三&#xff09;示例 &#xff08;四&#xff09;线程优缺点 线程的优点 线程的缺点 &#xff08;五&#xff09;线程和进程的切换 1.线程的切换 2.进程的切换…

【Docker学习】重启容器的docker restart

命令&#xff1a; docker container restart 描述&#xff1a; 重启一个或多个容器 用法&#xff1a; docker container restart [OPTIONS] CONTAINER [CONTAINER...] 别名&#xff1a; docker restart(docker的一些命令可以简写&#xff0c;docker restart就等同于docker cont…

对Windows超融合S2D的一些补充

先说一个不知道算不算BUG的例子&#xff0c;下面这个存储池是用两台服务器各2块10G建立的&#xff0c;除去系统保留的部分&#xff0c;显示还有13G可用。 但如果使用其新建虚拟磁盘会显示可用的空间为0 然后我又各增加了一块10G硬盘进池&#xff0c;变成了可用空间为30.5GB …