【蓝桥杯C/C++】专题六:动态规划
专题六:动态规划
目录
- 专题六:动态规划
- 导读
- 什么是动态规划
- 解决的问题
- 解题步骤
- 动态规划应该如何debug
- 记忆化搜索
- 斐波那契数
- 题目
- 代码
- 题解
- 爬楼梯
- 题目
- 代码
- 题解
- 使用最小花费爬楼梯
- 题目
- 代码
- 题解
- 不同路径
- 题目
- 题解
- dfs
- dp
- 凑硬币
- 题目
- 题解
- dfs
- dp
- 滑雪
- 题目
- 代码
- 题解
- 汉罗塔
- 题目
- 题解
- dfs
- dp
- 01背包问题
- 题目
- 代码
- 题解
- 摘花生
- 题目
- 代码
- 题解
- 最长上升子序列
- 题目
- 代码
- 题解
- 总结
在这里插入图片描述
导读
本专题将讲解最难理解的算法之一:动态规划。介绍动态规划的基本概念、算法原理以及应用场景。首先,我们将介绍动态规划的定义和特点,以及它与递归、贪心算法的区别。接着,我们将详细介绍动态规划的解题思路和算法流程,包括状态转移方程、边界条件、初始化等概念。最后,我们将讨论动态规划在实际问题中的应用,包括背包问题、最长公共子序列问题、最短路径问题等。
什么是动态规划
动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题于最优子问题,使用动态规划是最有效的。
所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的.
例如:有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i]
,得到的价值是value[i]
。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
动态规划中dp[j]
是由dp[j-weight[i]]
推导出来的,然后取max(dp[j], dp[j - weight[i]] + value[i])
。
但如果是贪心呢,每次拿物品选一个最大的或者最小的就完事了,和上一个状态没有关系。
所以贪心解决不了动态规划的问题。
解决的问题
动态规划是一种数学方法,用于求解决策过程的最优化问题。如果一个问题可以分解成若干个子问题,并且子问题之间还有重叠的更小的子问题,就可以考虑使用动态规划来解决这个问题。应用动态规划之前要分析能否把大问题分解成小问题,分解后的每个小问题也存在最优解。如果将小问题的最优解组合起来能够得到整个问题的最优解,那么就可以使用动态规划解决问题。可以应用动态规划求解的问题主要具有以下四个特点:
- 问题是求最优解。
- 整体问题的最优解依赖于各个子问题的最优解。
- 大问题分解成若干小问题,这些小问题之间还有相互重叠的更小的子问题。
- 从上往下分析问题,从下往上求解问题。
解题步骤
对于动态规划问题,我将拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
分享两张两种解决动态规划的思维导图:
动态规划应该如何debug
找问题的最好方式就是把dp数组打印出来,看看究竟是不是按照自己思路推导的!
做动规的题目,写代码之前一定要把状态转移在dp数组的上具体情况模拟一遍,心中有数,确定最后推出的是想要的结果。
然后再写代码,如果代码没通过就打印dp数组,看看是不是和自己预先推导的哪里不一样。
如果打印出来和自己预先模拟推导是一样的,那么就是自己的递归公式、初始化或者遍历顺序有问题了。
如果和自己预先模拟推导的不一样,那么就是代码实现细节有问题。
记忆化搜索
可以理解为实现dp的另一种方法,用递归实现本质还是搜索。
记忆化搜索按照自顶向下的顺序,每求得一个状态时,就把它的解保存下来,以后再次遇到这个状态时就不用重复求解了。
记忆化搜索包含两个要素记忆化和搜索。
- 沿用搜索的一般模式,本质还是用递归函数实现。
- 在搜索的过程中将已经得到的解保存起来,下次需要时直接用。
斐波那契数
题目
斐波那契数 (通常用 F(n)
表示)形成的序列称为 斐波那契数列 。该数列由 0
和 1
开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给定 n
,请计算 F(n)
。
示例 1:
输入: n = 2
输出: 1
解释: F(2) = F(1) + F(0) = 1 + 0 = 1
示例 2:
输入: n = 3
输出: 2
解释: F(3) = F(2) + F(1) = 1 + 1 = 2
示例 3:
输入: n = 4
输出: 3
解释: F(4) = F(3) + F(2) = 2 + 1 = 3
提示:
0 <= n <= 30
代码
class Solution {
public:int fib(int n) {if(n<2) return n;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];// cout<<dp[i]<<endl;}return dp[n];}
};
题解
动态规划五部曲:
-
确定dp数组以及下标的含义
dp[i]定义为:第i个数的斐波那契值为
dp[i]
-
确定递推公式
状态转移方程:
dp[i]=dp[i-1]+dp[i-2]
-
dp数组如何初始化
dp[0]=0; dp[1]=1;
-
确定遍历顺序
从前往后循环遍历,dp问题一般都是自底向上去思考。
爬楼梯
题目
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入: n = 2
输出: 2
解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2:
输入: n = 3
输出: 3
解释: 有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
提示:
1 <= n <= 45
代码
class Solution {
public:int climbStairs(int n) {if (n <= 1) return n; // 因为下面直接对dp[2]操作了,防止空指针vector<int> dp(n + 1);dp[1] = 1;dp[2] = 2;for (int i = 3; i <= n; i++) { // 注意i是从3开始的dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
};
题解
爬到第一层楼梯有一种方法,爬到二层楼梯有两种方法。
那么第一层楼梯再跨两步就到第三层 ,第二层楼梯再跨一步就到第三层。
所以到第三层楼梯的状态可以由第二层楼梯 和 到第一层楼梯状态推导出来,那么就可以想到动态规划了。
- 确定dp数组以及下标的含义
dp[i]: 爬到第i层楼梯,有dp[i]种方法
2 . 确定递推公式
如果可以推出dp[i]呢?
从dp[i]的定义可以看出,dp[i] 可以有两个方向推出来。
首先是dp[i - 1]
,上i-1层楼梯,有dp[i - 1]
种方法,那么再一步跳一个台阶不就是dp[i]了么。
还有就是dp[i - 2]
,上i-2层楼梯,有dp[i - 2]
种方法,那么再一步跳两个台阶不就是dp[i]了么。
使用最小花费爬楼梯
题目
给你一个整数数组 cost
,其中 cost[i]
是从楼梯第 i
个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0
或下标为 1
的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例 1:
输入: cost = [10,15,20]
输出: 15
解释: 你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。
示例 2:
输入: cost = [1,100,1,1,1,100,1,1,100,1]
输出: 6
解释: 你将从下标为 0 的台阶开始。
- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
- 支付 1 ,向上爬一个台阶,到达楼梯顶部。
总花费为 6 。
提示:
2 <= cost.length <= 1000
0 <= cost[i] <= 999
代码
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()];}
};
题解
- 确定dp数组以及下标的含义
使用动态规划,就要有一个数组来记录状态,本题只需要一个一维数组dp[i]就可以了。
dp[i]的定义:到达第i台阶所花费的最少体力为dp[i]。
对于dp数组的定义,大家一定要清晰!
- 确定递推公式
可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]。
dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。
dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。
那么究竟是选从dp[i - 1]跳还是从dp[i - 2]跳呢?
一定是选最小的,所以dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
- dp数组如何初始化
看一下递归公式,dp[i]由dp[i - 1],dp[i - 2]推出,既然初始化所有的dp[i]是不可能的,那么只初始化dp[0]和dp[1]就够了,其他的最终都是dp[0] dp[1]推出。
- 确定遍历顺序
最后一步,递归公式有了,初始化有了,如何遍历呢?
本题的遍历顺序其实比较简单,简单到很多同学都忽略了思考这一步直接就把代码写出来了。
因为是模拟台阶,而且dp[i]由dp[i-1]dp[i-2]推出,所以是从前到后遍历cost数组就可以了。
不同路径
题目
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
示例 1:
输入: m = 3, n = 7
输出: 28
示例 2:
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
- 向右 -> 向下 -> 向下
- 向下 -> 向下 -> 向右
- 向下 -> 向右 -> 向下
示例 3:
输入: m = 7, n = 3
输出: 28
示例 4:
输入: m = 3, n = 3
输出: 6
提示:
1 <= m, n <= 100
- 题目数据保证答案小于等于
2 * 109
题解
dfs
注意题目中说机器人每次只能向下或者向右移动一步,那么其实
机器人走过的路径可以抽象为一棵二叉树,而叶子节点就是终点!
此时问题就可以转化为求二叉树叶子节点的个数
class Solution {
private:int dfs(int i, int j, int m, int n) {if (i > m || j > n) return 0; // 越界了if (i == m && j == n) return 1; // 找到一种方法,相当于找到了叶子节点return dfs(i + 1, j, m, n) + dfs(i, j + 1, m, n);}
public:int uniquePaths(int m, int n) {return dfs(1, 1, m, n);}
};
dp
-
dp数组的定义
dp[i][j]:表示从(0,0)出发到(i,j)的不同路径
-
确定递推顺序
每个位置只有两个方向能走到,
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
-
数组初始化
从(0,0)到(i,0)的位置一定只有一种,到(0,j)也同理
for (int i = 0; i < m; i++) dp[i][0] = 1; for (int j = 0; j < n; j++) dp[0][j] = 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 - 1][j] + dp[i][j - 1];}}return dp[m - 1][n - 1];}
};
凑硬币
题目
题解
dfs
#include<bits/stdc++.h>
using namespace std;
/*
coins:硬币的面额列表;
amount:需要凑的金额;
count:当前使用硬币的数量;
index:当前搜索的硬币面额的下标;
res:存储最少的硬币数量。
*/
void dfs(vector<int>& coins, int amount, int count, int index, int& res) {if (amount == 0) {res = min(res, count);return;}if (index == coins.size()) {return;}for (int k = amount / coins[index]; k >= 0 && count + k < res; k--) {dfs(coins, amount - k * coins[index], count + k, index + 1, res);}
}int coinChange(vector<int>& coins, int amount) {sort(coins.rbegin(), coins.rend());int res = INT_MAX;dfs(coins, amount, 0, 0, res);return (res == INT_MAX ? -1 : res);
}int main() {vector<int> coins = {1, 2, 5};int amount;cin>>amount;int res = coinChange(coins, amount);cout << res << endl;return 0;
}
dp
#include<bits/stdc++.h>
using namespace std;
int amount;
vector<int> coins={1,2,5};int main()
{cin>>amount;vector<int> dp(amount+1,amount+1);//初始值也为amount + 1,是取不到的dp[0]=0;for(int i=0;i<dp.size();i++){for(auto e:coins){if(i-e<0) continue;dp[i]=min(dp[i],dp[i-e]+1);}}if(dp[amount]==amount+1) cout<<-1<<endl;else cout<<dp[amount];
}
dp数组定义:凑其前i金额需要的硬币数量。
初始值也为amount + 1,是取不到的
base case:自底向上思考,dp[0]
为0:金额为0时就不再需要硬币了
选择:从硬币面值组合里面选
状态:假设前i-1个已经选完了,最后选一个正好凑完
状态转移: dp[i]=min(dp[i],dp[i-e]+1);
需要判断i-e是否>0
滑雪
题目
代码
#include<bits/stdc++.h>
using namespace std;
const int N=310;
int n,m;
int g[N][N];//不能存在有环图
int f[N][N];//所有从i,j开始滑的路径,属性是max
//集合分为四类,向上向右向左向下
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};int dp(int x,int y)
{int &v=f[x][y];//引用即为取别名if(v!=-1) return v;//表示已经算过了v=1;//最小值为1for(int i=0;i<4;i++){int a=x+dx[i],b=y+dy[i];if(a>=1&&a<=n&&b>=1&&b<=m&&g[x][y]>g[a][b])v=max(v,dp(a,b)+1);}return v;
}
int main()
{cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>g[i][j];memset(f,-1,sizeof f);//初始化表示每个路径都没被算过int res=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)res=max(res,dp(i,j));cout<<res<<endl;return 0;
}
题解
本题考察使用记忆化搜索优化dp的算法
思路是:枚举路径上的每一个点,找到最大值,而每一个点又能分为四种小的递推的状态,因此可以使用动态规划来解决。
dp数组:使用一个二维数组来表示路径的长度
属性:最大值,满足条件即更新
记忆化搜索技巧:初始化数组表示没有被算过,如果已经被计算过就可以直接返回
汉罗塔
题目
题解
dfs
可以用dfs来搜索所有的情况取最大值
参数:
- index表示到第几层
- y表示枚举该层的第一个还是第二个数
- sum表示总和
#include<bits/stdc++.h>
using namespace std;const int N=10;
int f[N][N];int ans;
int n;
void dfs(int index,int y,int sum)
{if(index==n){ans=max(ans,sum);return ;}dfs(index+1,y,sum+f[index+1][y]);dfs(index+1,y+1,sum+f[index+1][y+1]);
}int main()
{cin>>n;for(int i=0;i<n;i++)for(int j=0;j<=i;j++){cin>>f[i][j];}dfs(0,0,f[0][0]);cout<<ans<<endl;
}
dp
#include<bits/stdc++.h>
using namespace std;const int N=10;
int f[N][N];
int dp[N][N];//表示从i,j到最后一层路径中的最大数字之和
int n;int main()
{cin>>n;for(int i=0;i<n;i++)for(int j=0;j<=i;j++){cin>>f[i][j];}for(int i=0;i<n;i++){dp[n-1][i]=f[n-1][i];//处理边界}//从后往前枚举for(int i=n-2;i>=0;i--){for(int j=0;j<=i;j++){dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+f[i][j];//递推式}}cout<<dp[0][0]<<endl;}
注意本题是从后往前枚举,根据dp数组的定义从i,j到最后一层路径中的最大数字之和,也就是要输出
dp[0][0]
01背包问题
题目
代码
#include<bits/stdc++.h>
using namespace std;const int N=10010;
int n,V;
int v[N],w[N];
int f[N][N];//从i个物品中选,体积不超过jint main()
{cin>>n>>V;for(int i=1;i<=n;i++)cin>>v[i]>>w[i];for(int i=1;i<=n;i++)for(int j=1;j<=V;j++){// 当前背包容量装不进第i个物品,则价值等于前i-1个物品if(j<v[i]) f[i][j]=f[i-1][j];// 能装,需进行决策是否选择第i个物品else{f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);}}cout<<f[n][V]<<endl;}
题解
摘花生
题目
代码
#include<bits/stdc++.h>
using namespace std;const int N=110;
int a[N][N];
int dp[N][N];//从(1,1)到(i,j)所有路径中能摘得花生最多的路径
int t;
int n,m;
int main()
{cin>>t;while(t--){cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>a[i][j];for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)dp[i][j]=max(dp[i-1][j]+a[i][j],dp[i][j-1]+a[i][j]);cout<<dp[n][m]<<endl;}}
题解
用闫式dp法来分析:
最长上升子序列
题目
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1010;int a[N];
int dp[N];//表示以i结尾的最长上升子序列
int n;
int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++)dp[i]=1;for(int i=1;i<=n;i++)for(int j=1;j<i;j++){if(a[i]>a[j])dp[i]=max(dp[i],dp[j]+1);}int res=0;for(int i=1;i<=n;i++)res=max(res,dp[i]);cout<<res<<endl;
}
题解
总结
动态规划是一种非常重要的算法思想,它可以解决很多实际问题,并且在计算机科学领域中有着广泛的应用。通过本博客的学习,我们可以了解到动态规划的基本概念、算法原理和应用场景。
在实际应用中,动态规划算法可以用于解决很多优化问题,如背包问题、最长公共子序列问题、最短路径问题等。学习动态规划算法不仅可以提高算法设计和解决问题的能力,还可以帮助我们更好地理解计算机科学中的一些基本概念和方法。
总之,动态规划算法是一种非常重要的算法思想,需要我们不断地学习和实践,才能更好地掌握它的精髓,并将其应用到实际问题中。希望本博客能够为读者提供一些启示和帮助,促进大家在算法学习和实践中的进步和成长。也祝大家考出好成绩!!
相关文章:

【蓝桥杯C/C++】专题六:动态规划
专题六:动态规划 目录专题六:动态规划导读什么是动态规划解决的问题解题步骤动态规划应该如何debug记忆化搜索斐波那契数题目代码题解爬楼梯题目代码题解使用最小花费爬楼梯题目代码题解不同路径题目题解dfsdp凑硬币题目题解dfsdp滑雪题目代码题解汉罗塔…...

图的定义和基本术语
图的定义和基本术语1.图的定义2.图的基本术语3.图的分类1.图的定义 图是由顶点和有穷非空集合和顶点边的集合吗,表示为G(V,E)。 G表示一个图,V是图G的顶点(数据元素)的集合,E是图G中顶点之间边的集合。在图中…...

041:cesium加载Blue Marble地图
第041个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载Blue Marble地图。Blue Marble是一个术语,用来描述星球漂浮在浩瀚太空中的形象。早在 1972 年,阿波罗 17 号任务的工作人员就首次捕捉到了地球的标志性卫星图像,并将其称为“Blue Marble”。从那时起,NA…...

【概念梳理】激活函数
一、引言 常用的激活函数如下: 1、Sigmoid函数 2、Tanh函数 3、ReLU函数 4、ELU函数 5、PReLU函数 6、Leaky ReLU函数 7、Maxout函数 8、Mish函数 二、激活函数的定义 多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,…...

【python】@property 和 @staticmethod
property 和 staticmethod 是 Python 中的两个装饰器,它们分别用于在类中创建属性或静态方法。它们的作用如下: property property:用于将类的一个方法作为属性访问。在 Python 中,使用“getter” 和“setter”方法来实现属性&a…...

Spring题集 - Spring AOP相关面试题总结
文章目录01. Spring AOP 的理解?02. Spring AOP 思想的代码实现03. Spring AOP 的相关术语有哪些?04. Spring AOP 基于注解的切面实现?05. Spring AOP 的通知有哪些类型?06. AOP 有哪些实现方式?07. Spring AOP 和 AspectJ AOP 有…...

分考场
[蓝桥杯 2017 国 C] 分考场(假题:最小色数) 题目描述 nnn 个人参加某项特殊考试。 为了公平,要求任何两个认识的人不能分在同一个考场。 求最少需要分几个考场才能满足条件。 输入格式 第一行,一个整数 n(1<n<100)n(1<n<100…...

BI技巧丨DAX Studio
DAX Studio DAX Studio,作为PowerBI外部插件使用率排名第一的插件,相信各位小伙伴或多或少都听说过,那么DAX Studio具体有哪些功能呢? PS:DAX Studio的下载链接,小伙伴们可以自行搜索,这里就不…...

Java 8常用时间 API
Date: 你不爱我了吗? 🚡本地时间时区相关格式化在Java 8中,Instant类用于表示时间戳,相当于旧的Date类;LocalDateTime类用于表示日期和时间,相当于旧的Calendar类;DateTimeFormatter类用于格式化日期和时间…...

C++运算符
C运算符 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 内置了丰富的运算符,并提供了以下类型的运算符: 算术运算符关系运算符逻辑运算符位运算符赋值运算符杂项运算符 1. 算术运算符 运算符描述实例把两个操作数相加A B 将得到 30-从第…...

低/无代码赋能企业,IT与业务的角色正在悄然改变
现在这个社会,年轻人的压力是真的大,需要会的技能多到数不清。想学习多点技能也不知道去哪学,主要是网络资源太丰富,很难找到一个适合自己的。那接下来推荐4个大神级别的资源网站你可一定得码住,都是年轻人特别 …...

SpringCloud学习2(Spring Cloud Netflix)负载均衡Ribbon、Feign负载均衡、Hystix服务熔断
文章目录负载均衡RibbonRibbon的作用代码实现生产者cloud1_provider实现配置文件在HiController中编写以下代码启动集群消费者cloud1_consumer实现引入依赖编写配置文件编写启动类,并给RestTemplate配置LoadBalanced注解编写RestController来测试Feign负载均衡简介F…...

Spring 源码解析 - @Async 注解下的循环依赖问题原理
一、Async 注解下的循环依赖问题 我们都知道 Spring IOC 单例模式下可以帮助我们解决循环依赖问题,比如下面自己依赖自己循环依赖的场景: Component public class TestAsync {ResourceTestAsync async;public void test() {System.out.println("t…...

8个全球性编程比赛,天才程序员的梦想舞台
很多编程爱好者在学习之初,都渴望与全球的程序员一较高下,以证明自己的实力。 一些全球性的编程竞赛为他们提供了这样的机会,不仅可以与全世界的顶尖程序员们交流,还有机会获得丰厚的奖金和进入顶级公司的机会,更重要…...

2023年中国海洋大学计算机及电子信息考研分析
考研时间跨度: 初试时间: 2022年8月23 海大推免及创新人才计划接收通知。 2022年9月13 海大专业目录及人数,包含推免。 2022年10月18 2022年硕士研究生计划 ,不含推免。 海大2022年硕士研究生计划 网上第一次时间为2022年9月24日…...

【C++笔试强训】第六天
选择题 1. 解析:十进制转换为八进制就是不断的除8,取余数。十进制转换成其他进制的数就是除以进制,取余。 解析:注意printf的转换,%%只会打印一个%,所以选A。 解析:由于()的原因p先和*结合&…...

Redission 中的 RedLock 原理实现, springboot 你造吗?
分布锁之RedLock 锁住你的心我的爱 🚂为什么需要使用 RedLock锁被误释放时钟不一致问题锁的“延迟释放”而不是死锁Redlock是啥redlock 存在什么问题惊群效应时钟漂移Redisson 实现 RedLock在 Redisson 中, RedLock的实现类是哪一个类?这一招叫抛砖引玉springboot …...

【沐风老师】3dMax一键房屋创建者插件使用方法详解
3dmax一键房屋创建者,一键生成墙体、窗洞和门洞的插件!这个脚本主要用于创建或捕获一些架构项目所代表的平面,这是通过导入它们并在每个所需的层添加值来实现的。传统方法,但是省事儿多了! 【版本要求】 3dMax 2015及…...

C/C++ 变量详解
文章目录前言一、静态变量与动态变量1. 概念2. 区别3. 使用方法和注意事项3.1 静态变量3.2 动态变量4. 结论二、全局变量与局部变量1. 区别2. 全局变量的使用方法和注意事项3. 局部变量的使用方法和注意事项4. 总结前言 对C学习感兴趣的可以看看这篇文章哦:C/C教程…...

新SSD盘安装操作系统启动不了
今天打算给电脑升级下装备,加装一块固态硬盘。 电脑原本自带两块硬盘(SSD128GSATA1T),SSD清理了许久还是没空间,于是就买了块1TSSD,打算扩容下。 打开电脑后盖傻眼了,没有备用插槽,…...

基于Spring、SpringMVC、MyBatis的病历管理系统
文章目录 项目介绍主要功能截图:登录首页医院公告管理用户管理科室信息管理医生管理出诊信息管理预约时间段管理预约挂号管理门诊病历管理就诊评价管理轮播图管理功能架构图部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历…...

QT编程从入门到精通之三十四:“第五章:Qt GUI应用程序设计”之“5.5 Qt Creator使用技巧”
目录 第五章:Qt GUI应用程序设计 5.5 Qt Creator使用技巧 第五章:Qt GUI应用程序设计 在“Qt 程序创建基础”上,本章将继续深入地介绍Qt Creator设计GUI应用程序的方法,包括Qt创建的应用程序项目的基本组织结构,可视化设计的UI界面文件的原理和运行机制,信号与槽的使用…...

网络工程方向有哪些SCI期刊推荐? - 易智编译EaseEditing
以下是网络工程领域的一些SCI期刊推荐: IEEE Transactions on Network and Service Management: 这是一个IEEE旗下的期刊,涵盖了网络与服务管理方面的研究。主要关注网络管理、服务管理和其它相关领域的创新和最新研究。 Computer Networks: 这是一本著…...

netty入门(二十六)任务加入异步线程池源码剖析
1.handler中加入线程池和Context添加线程池 1.1 源码剖析目的 (1)在 Netty 中做耗时的,不可预料的操作,比如:数据库、网络请求、会严重影响 Netty 对 Socket 的处理速度。 (2)而解决方法就是…...

神经网络算法入门和代码
文章内容 感知机(Perceptron)反向传播算法(Back Propagation algorithm)RBF(Radial Basis Function,径向基函数) 网络:单一层前馈网络,它使用径向基作为隐层神经元激活函数ART(Adaptive Resona…...

如何用一个端口同时暴露 HTTP1/2、gRPC、Dubbo 协议?
作者:华钟明 本文我们将介绍 Apache Dubbo 灵活的多协议设计原则,基于这一设计,在 Dubbo 框架底层可灵活的选用 HTTP/2、HTTP/REST、TCP、gRPC、JsonRPC、Hessian2 等任一 RPC 通信协议,同时享用统一的 API 与对等的服务治理能力。…...

ToBeWritten之杂项2
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬…...

Linux三剑客之awk命令详解
1、概述 Linux三剑客:grep、sed、awk。grep主打查找功能,sed主要是编辑行,awk主要是分割列处理。本篇文章我们详细介绍awk命令。 awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。awk是一种编…...

C++异常处理:掌握高效、健壮代码的秘密武器
C异常处理全面解析:底层原理、编译器技巧与实用场景C异常机制:让我们迈向更安全、更可靠的代码C异常处理:掌握基本概念什么是异常?异常处理的重要性C异常处理的组成部分:try、catch、throw探索C异常处理的核心…...

Jetpack Compose基础组件之按钮组件
概述 按钮组件Button是用户和系统交互的重要组件之一,它按照Material Design风格实现,我们先看下Button的参数列表,通过参数列表了解下Button的整体功能 Composable fun Button(onClick: () -> Unit, // 点击按钮时的回调modifier: Modi…...