蓝桥杯c++算法秒杀【6】之动态规划【上】(数字三角形、砝码称重(背包问题)、括号序列、组合数问题:::非常典型的必刷例题!!!)
下将以括号序列、组合数问题超级吧难的题为例子讲解动态规划
别忘了请点个赞+收藏+关注支持一下博主喵!!!! ! ! ! !
关注博主,更多蓝桥杯nice题目静待更新:)
动态规划
一、数字三角形
【问题描述】
上图给出了一个数字三角形。从三角形的顶部到底部有很多条路径。对于每条路径, 把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右边的那个 数。此外,向左下走的次数与向右下走的次数相差不能超过1。
【输入格式】
输入的第一行包含一个整数N(1⩽N⩽100),表示三角形的行数。
下面的N行给出数字三角形。数字三角形上的数都是0至100之间的整数。
【输出格式】
输出一个整数表示答案。
【样例输入】
【样例输出】
27
解析:
本题是十分经典的动态规划题。
为了方便存储与操作,可以将题目描述中的等腰三角形转换为直角三角形,如下图所示。
将其转换为直角三角形后,就可以用一个二维数组(a[][])来存储它。这样三角形第i行 的第j 个数字就可以通过a[i][j] 来表示。同时原来向左下走就变为了向下走,本题下文解析所说的“向下走”即为“向左下走”,向右下走还是向右下走。
在处理完样例输入后,我们来尝试对题目进行求解。
由于“向左下走的次数与向右下走的次数相差不能超过1”这个限制条件看上去比较复杂,所以我们可将该题分解为两个子问题: 第一个子问题是不考虑限制条件,只解决如何走的问题;第二个子问题是加上这个限制条件找到走到底部的最大路径和,从而完整解答出本题。对于每个子问题,都分别用DFS和动态规划两种方式来解题,大家可进一步体验这两种方式的特点。
解决子问题1:DFS模式
题目要求我们从三角形的顶部开始走,而顶部只有一个数字a[1][1],所以所走路径的起点一定是a[1][1]。
由于我们每一步只能向下走或者向右下走,因此a[1][1]的下一步只有以下两种可能。
(1)走向a[2][1]。
(2)走向a[2][2]。
具体要走向哪个呢?我们并不好确定。
我们能得知的是,如果设dfs(i,j) 表示从 a[i][j] 走到底部的最大路径和,那么我们一定会走向max(dfs(2,1),dfs(2,2)) 所对应的路径,即从 a[1][1] 走到底部的最大路径和:
在该式子中,dfs(1,1) 是我们要求解的,a[1][1] 是已知的,dfs(2,1)、dfs(2,2) 是未知的。 显然,只要存在未知数,就无法求解dfs(1,1)的值。因此,必须先求解dfs(2,1) 和dfs(2,2)。
但要怎么求解它们呢? 我们以求解dfs(i,j) 为例。
当a[i][j](i < n) 不在底部时,每一步只能向下走或者向右下走,因此a[i][j] 的下一步只有两种可能。
(1)走向a[i+1][j]。
(2)走向a[i+1][j +1]。 当a[i][j](i = n) 在底部时,我们将无法再走任何一步。 由此可得 :
参考代码如下 【时间复杂度为 O()】
#include <bits/stdc++.h>
using namespace std;const int N = 1e2 + 10;
int n, a[N][N];int dfs(int i, int j) {if (i == n) return a[i][j]; // 走到底部无法再走了,直接返回return max(dfs(i + 1, j), dfs(i + 1, j + 1)) + a[i][j];
}signed main() {cin >> n;for (int i = 1; i <= n; i++) {for (int j = 1; j <= i; j++) {cin >> a[i][j];}}cout << dfs(1, 1) << '\n';return 0;
}
在上方代码中,每次dfs都几乎调用了自己两次,所以代码的时间复杂度约为O()。
如果一个三角形的行数为4,则程序的递归过程将如下图所示。
显然,O() 的时间复杂度是十分低效的,无法帮助我们顺利解出本题。至于复杂度低效的原因,从上图中不难发现是因为在递归的过程中做了过多重复的计算,比如在上图中, dfs(3, 2) 就重复计算了一次。
那么,我们要如何避免递归时的重复计算呢?
可以采用一个简单且高效的方法——记忆化,即定义一个二维数组res[][],用res[i][j]保 存dfs(i,j) 的计算结果。当再次需要dfs(i,j) 的计算结果时,直接返回res[i][j] 即可,无须继续递归下去。
使用了记忆化的方法优化后,最多只需进行约次递归。
参考代码如下 【时间复杂度为 O()】
#include <bits/stdc++.h>
using namespace std;const int N = 1e2 + 10;
int n, a[N][N], res[N][N];int dfs(int i, int j) {if (res[i][j]) return res[i][j]; // 如果 res[i][j] 不为 0,说明已经计算过,直接返回结果if (i == n) return a[i][j]; // 到达底部,返回当前值return res[i][j] = max(dfs(i + 1, j), dfs(i + 1, j + 1)) + a[i][j]; // 计算并存储结果
}signed main() {cin >> n;for (int i = 1; i <= n; i++) {for (int j = 1; j <= i; j++) {cin >> a[i][j];}}cout << dfs(1, 1) << '\n';return 0;
}
解决子问题1:动态规划模式
与DFS 不同的是,动态规划通常是采用递推的方式从上到下来求解问题。
在本题中,我们从三角形的顶部(1,1)走到三角形的某个位置(i,j)的方法颇多,根据不同的走法,所得到的路径和可能会有所差异。
由于本题需要求解的是从三角形顶部(1,1) 走到底部的最大路径和,所以在不同方法带 来的不同路径和中,我们只需要关注最大路径和即可。
于是,我们可以定义一个数组dp[][],其中dp[i][j] 用以表示从三角形顶部(11) 走到(ij) 的所有路径和中的最大值。
当走到底部时,所处的位置可能有(n,1)、(n,2)、...、(n,n),它们对应的最大路径和分 别为dp[n][1]、dp[n][2]、...、dp[n][n]。我们要的是这当中的最大路径和,即 。
起初,处于三角形的顶部(1,1)。因为从(1,1) 走到(1,1) 的方法仅有一种,所以我们可 得dp[1][1] = a[1][1]。
(1)从位置(i−1,j) 向下走一步。
(2)从位置(i−1,j−1) 向右下走一步。
无论我们选择哪种,从(1,1) 到(i,j) 的路径与 (1,1) 到 (i−1,j) 或 (i−1,j−1) 的路径都只会有一步之差。所以两种方法到达(i,j)的最大路径和分别如下。
(1)dp[i−1][j]+a[i][j]。
(2)dp[i−1][j −1]+a[i][j]。
为了使到达位置(i,j) 的路径和最大,我们需要从这两种方法中选择较大的一种,即
这样,我们便完成了dp方程的转移。
参考代码如下 【时间复杂度为 O()】
#include <bits/stdc++.h>
using namespace std;const int N = 1e2 + 10;
int n, a[N][N], dp[N][N];signed main() {cin >> n;for (int i = 1; i <= n; i++) {for (int j = 1; j <= i; j++) {cin >> a[i][j];}}dp[1][1] = a[1][1];for (int i = 2; i <= n; i++) {for (int j = 1; j <= i; j++) {dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + a[i][j];}}int ans = 0;for (int j = 1; j <= n; j++) {ans = max(ans, dp[n][j]);}cout << ans << '\n';return 0;
}
提示: 以上情况都是在不考虑“向左下走的次数与向右下走的次数相差不能超过1”这个限制 条件下分析的,接下来我们来思考加上向左下走的次数与向右下走的次数相差不能超过1这个限制条件之后该如何处理,即解决子问题2。
为了方便读者理解,接下来我们分别用动态规划和DFS两种方法对本题进行讲解。
解决子问题2:动态规划模式
我们可以采用最简单的方法:从顶部向底部走的过程中,额外添加一个状态——向下走 的次数,即定义dp[i][j][k]表示从(1,1)走到(i,j)一共向下走了k次的最大和。
根据向下走和向右下走的次数相差不能超过1的条件,那么从第1行到第n行一共要走 n−1步,由此可得:
•当n−1为奇数(n为偶数)时,向下走的次数可以为 ,也可以为
+1;
•当n−1为偶数(n为奇数)时,向下走的次数只能为 。
那么答案就可表示为:
对于位置(i,j),它可以由位置 (i − 1,j) 向下走了一步得到,也可以由位置(i−1,j−1) 向右下走了一步得到,于是dp转移方程为
参考代码如下【时间复杂度为O()】
#include <bits/stdc++.h>
using namespace std;const int N = 1e2 + 10;
int n, a[N][N], dp[N][N][N];signed main() {memset(dp, -0x3f, sizeof(dp)); // 某些情况可能并不存在,如 dp[2][1][0]:走到位置 (2,1) 时共向下走了 0 次。为了防止这种情况被转移,需初始化 dp 数组cin >> n;for (int i = 1; i <= n; i++) {for (int j = 1; j <= i; j++) {cin >> a[i][j];}}dp[1][1][0] = a[1][1];for (int i = 2; i <= n; i++) {for (int j = 1; j <= i; j++) {for (int k = 0; k <= (n - 1); k++) {if (!k) {dp[i][j][k] = dp[i - 1][j - 1][k] + a[i][j];} else {dp[i][j][k] = max(dp[i - 1][j - 1][k], dp[i - 1][j][k - 1]) + a[i][j];}}}}int ma = 0;if ((n - 1) & 1) {for (int j = 1; j <= n; j++) {ma = max(ma, max(dp[n][j][(n - 1) / 2], dp[n][j][(n - 1) / 2 + 1]));}} else {for (int j = 1; j <= n; j++) {ma = max(ma, dp[n][j][(n - 1) / 2]);}}cout << ma << '\n';return 0;
}
虽说运用上述的方法已经可以完成本题了,但我们其实不额外添加一个状态也可以解决。 由上可得以下结论。
•当n−1为奇数(n为偶数)时,向下走的次数可以为 ,也可以为
+1;
•当n−1为偶数(n为奇数)时,向下走的次数只能为 。
基于向下走的次数、向右下走的次数限制不难发现以下情况。
•当n−1为奇数(n为偶数)时,无论中间的路线是什么样的,最后的位置只有两种可能:
( n , 1 + ),( n , 1 +
+ 1 )。
•当n为偶数时,无论中间的路线是什么样的,最后的位置只有一种可能:
( n , 1 + )。
所以我们并不需要考虑从顶部走到底部时向下走的次数,只需要保证最后的位置正确即可。
用dp[i][j]表示从(1,1)走到(i,j)的最大和并对其进行转移,那么答案就可以表示为:
参考代码如下【时间复杂度为O()】
#include <bits/stdc++.h>
using namespace std;const int N = 1e2 + 10;
int n, a[N][N], dp[N][N];signed main() {cin >> n;for (int i = 1; i <= n; i++) {for (int j = 1; j <= i; j++) {cin >> a[i][j];}}dp[1][1] = a[1][1];for (int i = 2; i <= n; i++) {for (int j = 1; j <= i; j++) {dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][j]) + a[i][j];}}// 根据 n-1 的奇偶性输出:在满足向下走的次数与向右下走的次数相差不能超过 1 的条件下可能会到达的位置对应的 dp 值if ((n - 1) & 1) {cout << max(dp[n][1 + (n - 1) / 2], dp[n][1 + (n - 1) / 2 + 1]) << '\n';} else {cout << dp[n][1 + (n - 1) / 2] << '\n';}return 0;
}
解决子问题2:DFS模式
DFS的处理方法和动态规划的类似,有以下两种方法:
(1)额外添加一个状态使得答案满足条件;
(2)保证最后的位置正确使得答案满足条件。
下面给出第二种方法的参考代码。
参考代码如下
#include <bits/stdc++.h>
using namespace std;const int N = 1e2 + 10;
int n, a[N][N], res[N][N];int dfs(int i, int j) {if (res[i][j]) return res[i][j]; // 如果 res[i][j] 不为 0,说明已经计算过,直接返回结果if (i == n) {if (n % 2 && j == n / 2 + 1) return a[i][j]; // n 为奇数且 j 为中间位置if (n % 2 == 0 && (j == n / 2 || j == n / 2 + 1)) return a[i][j]; // n 为偶数且 j 为中间两个位置之一return -10000000; // 位置不正确时,返回一个极大的负数}return res[i][j] = max(dfs(i + 1, j), dfs(i + 1, j + 1)) + a[i][j]; // 计算并存储结果
}signed main() {cin >> n;for (int i = 1; i <= n; i++) {for (int j = 1; j <= i; j++) {cin >> a[i][j];}}cout << dfs(1, 1) << '\n';return 0;
}
二、砝码称重
【问题描述】
你有一架天平和N个砝码,这N个砝码重量依次是W1,W2,...,WN。
请你计算一共可以称出多少种不同的重量。注意砝码可以放在天平两边。
【输入格式】
输入的第一行包含一个整数N。
第二行包含N个整数:W1,W2,W3,...,WN。
【输出格式】
输出一个整数表示答案。
【样例输入】
【样例输出】
10
【样例说明】
【评测用例规模与规定】
对于50% 的评测用例,1⩽ N ⩽15。
对于所有评测用例,1⩽ N ⩽100,N 个砝码总重不超过100000。
解析:
本题是道有限制的选择问题、背包问题的变形题。
在本题中,题目给定了1个天平及n个砝码,每个砝码都有自己的重量。天平存在以下 3 种状态。
(1)平衡。
(2)向左倾斜。
(3)向右倾斜。
这3种状态分别可称出的重量:
(1)0(忽略不计);
(2)左侧的砝码重量−右侧的砝码重量;
(3)右侧的砝码重量−左侧的砝码重量。
显然,天平的状态只会受到两侧砝码的重量影响。对于每个砝码,它都有以下3种处理方式。
(1)放在天平的左侧。
(2)放在天平的右侧。
(3)两侧都不放。
那么,n个砝码就有3n种处理方式(情况)。
在50%的评测用例中,1⩽n⩽15。当n=15时,315=14348907,数据规模为107 左右。
因此,我们可以使用直接dfs“暴力”搜索出放置n个砝码的所有情况,并统计这些情况能够称出的不同重量的个数。
(1)dfs“暴力”搜索
参考代码如下【时间复杂度为O()】
#include <bits/stdc++.h>
using namespace std;const int N = 1e2 + 10, M = 1e5 + 10;
int n, ans, w[N], vis[M]; // vis[x] = 1 表示可以称出重量 xvoid dfs(int i, int left, int right) {if (i > n) {vis[max(left, right) - min(left, right)] = 1;return;}// 将第 i 个砝码放置在左边dfs(i + 1, left + w[i], right);// 将第 i 个砝码放置在右边dfs(i + 1, left, right + w[i]);// 两边都不放dfs(i + 1, left, right);
}signed main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> w[i];}dfs(1, 0, 0);for (int i = 1; i < M; i++) {if (vis[i]) {ans++;}}cout << ans << '\n';return 0;
}
可当 1 ⩽ n ⩽100 时,还能用dfs搜索出所有情况吗?显然不行,因为当n=100时, 会是个天文数字,计算机在有限的时间内是不可能搜索出所有情况的。
那怎么办呢? 考虑用动态规划解决。
(2)动态规划【正解】
1. 设计状态数组
按照常规的步骤,我们会设计一个状态数组dp[],其中dp[i]表示用前i个砝码所能称出 的不同重量的个数。
这么设计看似合理,答案也可以用dp[n] 轻松表示,但略加思考后不难发现其存在一个 致命问题,即在状态转移的过程中,无法处理相同的重量被重复计算的情况。
如何解决这个致命问题呢?我们只要将重量也设计在状态数组中,即设计一个boolean类 型的二维数组dp[][],其中 dp[i][j] = true 表示前 i 个砝码能通过天平称出重量 j,dp[i][j]= false 则表示前 i 个砝码不能通过天平称出重量j。
由于n个砝码的总重量不超过100000,所以我们只要在求解完整个数组后,枚举dp[n][1∼ 100000],统计其中值为 true 的元素个数,即可得出 n 个砝码所能称出的不同重量的个数。
到这里貌似没有什么问题。那么接下来,我们就来讨论一下如何求解dp[][]数组。
2. 初始状态
起初,我们未在天平两侧放置任何砝码,天平它会处于一种平衡的状态。我们可以认为 此时天平称的重量为0,即dp[0][0]=true。
3. 推导转移方程
事实上,天平所称出的重量总是会由重的一侧减去轻的一侧,即对于第i个砝码,若我 们将其放入天平较重的一侧,则它将使天平称出的重量增加wi;若将该砝码放入天平较轻的 一侧,则它将使天平称出的重量减少wi。例如,在我们处理完前i−1个砝码后,天平所称 出的重量为j,那么在处理完第i个砝码后,天平所能称出的重量将会根据对第i个砝码不 同的处理方式得到3种不同结果分别如下。
(1)j+wi:将第i 个砝码放在较重的一侧。
(2)j−wi:将第i 个砝码放在较轻的一侧。
(3)j:两侧都不放。 因此,我们可推导出以下3种状态转移式:
因此,我们可推导出以下3种状态转移式:
若将3个状态转移式整合成一个,可得
完成状态转移式的推导。 值得注意的是,在进行状态转移的过程中,可能会出现 j < w[i] 的情况( j - w[i] < 0 )。若不进行处理,就会导致数组的越界,进而导致答案错误。
因此,我们可以为所有重量添加一个偏移量offset(对于重量x,用x+offset来表示它), 如下图所示,使得∀j−w[i]+offset⩾0。
提示:添加上offset 后,dp[i][j] 的含义为前 i 个砝码能否通过天平称出重量 j−offset。
参考代码如下【时间复杂度为 O(n× n ∑ i=1 wi)】
#include <bits/stdc++.h>
using namespace std;const int N = 1e2 + 10, M = 1e5 + 10, offset = 1e5;
int n, ans, w[N], dp[N][2 * M];signed main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> w[i];}dp[0][0 + offset] = true;for (int i = 1; i <= n; i++) {for (int j = 0; j < M + offset; j++) {if (j - w[i] >= 0) dp[i][j] |= dp[i - 1][j - w[i]];dp[i][j] |= dp[i - 1][j + w[i]] | dp[i - 1][j];}}for (int i = 1 + offset; i < M + offset; i++) {if (dp[n][i]) ans++;}cout << ans << '\n';return 0;
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
下将以括号序列、组合数问题超级吧难的题为例子讲解动态规划
别忘了请点个赞+收藏+关注支持一下博主喵!!!! ! ! !
关注博主,更多蓝桥杯nice题目静待更新:)
相关文章:
蓝桥杯c++算法秒杀【6】之动态规划【上】(数字三角形、砝码称重(背包问题)、括号序列、组合数问题:::非常典型的必刷例题!!!)
下将以括号序列、组合数问题超级吧难的题为例子讲解动态规划 别忘了请点个赞收藏关注支持一下博主喵!!!! ! ! ! ! 关注博主,更多蓝桥杯nice题目静待更新:) 动态规划 一、数字三角形 【问题描述】 上图给出了…...
c#:winform引入bartender
1、vs新建项目 ①选择Windows窗体应用(.NET Framework) 2、将bartender引入vs中 ①找到bartender的安装目录,复制Seagull.BarTender.Print.dll文件 ②粘贴到项目->bin->Debug文件,并可创建Model文件夹:为了存放…...
Zabbix 模板翻译自动化教程
在企业 IT 运维管理中,Zabbix 作为一款强大的开源监控平台被广泛应用。而 Zabbix 模板作为监控配置的重要组成部分,用来定义监控项、触发器、图形等。随着国际化的需求增加,Zabbix 模板的翻译工作变得日益重要,特别是在需要为不同…...
HarmonyOS开发:DevEco Studio的Beta3(5.0.5.200)新增和增强特性
新增特性 DevEco Studio支持开发API 13工程。DevEco Profiler Frame模板新增Lost Frames和Hitch Time泳道,用于识别和优化卡顿和丢帧现象。具体请参考Frame分析。hvigor-config.json5中properties下新增ohos.arkCompile.noEmitJs字段,用于指定ArkTS编译…...
macOS安装nvm node
macOS安装nvm macOS安装nvm创建 nvm 工作目录配置环境变量使用 nvm查看可用的 Node.js 版本安装特定版本 macOS安装nvm brew install nvm创建 nvm 工作目录 mkdir ~/.nvm配置环境变量 vim ~/.zshrc# nvm export NVM_DIR"$HOME/.nvm" [ -s "/opt/homebrew/opt…...
SpringBoot 集成MQTT实现消息订阅
1、引入依赖 <!--MQTT start--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-integration</artifactId></dependency><dependency><groupId>org.springframework.integrat…...
VM+Ubuntu18.04+XSHELL+VSCode环境配置
前段时间换了新电脑,准备安装Linux学习环境:VM虚拟机、Ubuntu18.04操作系统、XSHELL、XFTP远程连接软件、VSCode编辑器等,打算把安装过程记录一下。 1. 虚拟机介绍 为什么要用虚拟机? 想学习Linux操作系统,一般有3种…...
C#上机练习66-70
66.数组x中存有20个四位整数,请编制函数,求出正整数的个数tn。以及各位数字之和是偶数的数的个数tc,以及满足条件的这些数的算术平均ta.,将tn,tc,ta在控制台输出。 67.数组x中存有20个四位整数,请编制函数…...
pip 与当前python环境版本不匹配, pyenv, pipenv, conda
目录 pip 与当前python环境不匹配解决pip版本不一致 CondaPyenv pip 与当前python环境不匹配 电脑中安装了多个python虚拟环境, 有anaconda创建的虚拟环境,也有pyenv创建的虚拟环境,但是环境变量配置的是anaconda的路径 从而导致在vscode中选择的python版本是3.8.10,而pip却是…...
HAProxy面试题及参考答案(精选80道面试题)
目录 什么是 HAProxy? HAProxy 主要有哪些功能? HAProxy 的关键特性有哪些? HAProxy 的主要功能是什么? HAProxy 的作用是什么? 解释 HAProxy 在网络架构中的作用。 HAProxy 与负载均衡器之间的关系是什么? HAProxy 是如何实现负载均衡的? 阐述 HAProxy 的四层…...
ElasticSearch为什么不能在query阶段直接返回_id,从而避免fetch?
整理自Github的一个issue,也正好解答了我的疑惑 https://github.com/elastic/elasticsearch/issues/17159 提问 是否可以避免搜索的fetch阶段并仅返回文档ID?查询阶段结束时是否有_id,这样当我只需要_id时,fetch就多余了?可以通过…...
任意文件读取漏洞(CVE-2024-7928)修复
验证CVE-2024-7928问题是否存在可以使用如下方法: https://域名/index/ajax/lang?lang..//..//目录名/文件名(不带后缀) 目录名是该项目的一个目录,这里目录位置为nginx设置站点目录为基准,网上两层目录。 文件名…...
07 初始 Oracle 优化器
查询优化器,简称优化器,是数据库最核心的组件之一。我们在这个系列的第一篇文章中已经给大家介绍了,优化器会参与到SQL语句的解析过程中,用来生成SQL语句的执行计划,直接决定SQL语句执行性能的优劣。 什么是执行计划 …...
深入理解React Hooks:使用useState和useEffect
引言 React Hooks是React 16.8引入的一项强大功能,它使函数组件能够使用状态和其他React特性。本文将深入探讨两个最常用的Hooks:useState和useEffect,并通过实际代码示例展示它们的使用方法。 1. 什么是React Hooks? React Ho…...
深入浅出剖析典型文生图产品Midjourney
2022年7月,一个小团队推出了公测的 Midjourney,打破了 AIGC 领域的大厂垄断。作为一个精调生成模型,以聊天机器人方式部署在 Discord,它创作的《太空歌剧院》作品,甚至获得了美国「数字艺术/数码摄影」竞赛单元一等奖。 这一事件展示了 AI 在绘画领域惊人的创造力,让人们…...
大数据学习18之Spark-SQL
1.概述 1.1.简介 Spark SQL 是 Apache Spark 用于处理结构化数据的模块。 1.2.历史 1.2.1.Shark Hadoop诞生初期,Hive是唯一在Hadoop上运行的SQL-on-Hadoop工具,MR的中间计算过程产生了大量的磁盘落地操作,消耗了大量的I/O,降低…...
Flink开发入门简单案例--统计实时流订单
Flink开发入门简单案例 0.简介1.订单数据生成器1.1 新建工程TestFlink1.2 在pom.xml中引入Flink依赖包1.3 订单数据生成类订单类(Item)订单生成数据流类测试订单生成类 2.订单统计2.1 仅统计订单中商品的件数 2.2 同时统计商品数量和金额 0.简介 本案例…...
Scala身份证上的秘密以及Map的遍历
object test {def main(args: Array[String]): Unit {val id "42032220080903332x"//1.生日是?//字符串截取val birthday id.substring(10,14) //不包括终点下标println(birthday)val year id.substring(6,10) //println(year)//性别:倒数第…...
RabbitMQ
交换机 Fanout:广播Direct:定向路由Topic:匹配符 声明队列和交换机 基于Bean基于注解 消息转换器 JSON序列化...
全景图像(Panorama Image)向透视图像(Perspective Image)的跨视图转化(Cross-view)
一、概念讲解 全景图像到透视图像的转化是一个复杂的图像处理过程,它涉及到将一个360度的全景图像转换为一个具有透视效果的图像,这种图像更接近于人眼观察世界的方式。全景图像通常是一个矩形图像,它通过将球面图像映射到平面上得到…...
matlab 实现混沌麻雀搜索算法的光伏MPPT控制仿真
1、内容简介 略 103-可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...
【设计模式】【行为型模式(Behavioral Patterns)】之策略模式(Strategy Pattern)
1. 设计模式原理说明 策略模式(Strategy Pattern) 是一种行为设计模式,它允许你定义一系列算法,并将每个算法封装起来,使它们可以互换。策略模式让算法的变化独立于使用算法的客户。通过这种方式,客户端可…...
深度学习笔记之BERT(三)RoBERTa
深度学习笔记之RoBERTa 引言回顾:BERT的预训练策略RoBERTa训练过程分析静态掩码与动态掩码的比较模型输入模式与下一句预测使用大批量进行训练使用Byte-pair Encoding作为子词词元化算法更大的数据集和更多的训练步骤 RoBERTa配置 引言 本节将介绍一种基于 BERT \t…...
windows docker 入门
这个教程将指导你如何安装Docker、运行第一个容器以及理解一些基本概念。 第一步:安装Docker Desktop for Windows 系统要求: Windows 10 64位版本(专业版、企业版或教育版)。启用Hyper-V和Windows Subsystem for Linux (WSL 2)。…...
【软考速通笔记】系统架构设计师③——信息安全技术基础知识
文章目录 一、前言二、信息安全基础知识2.1 信息安全的基本要求2.2 信息安全的范围2.3 网络安全表现2.4 安全措施包括 三、信息安全系统的组成框架3.1 技术体系:3.2 组织机构体系:3.3 管理体系 四、信息加解密技术4.1 对称密钥加密算法4.2 非对称密钥加密…...
Spring Boot整合Redis Stack构建本地向量数据库相似性查询
Spring Boot整合Redis Stack构建本地向量数据库相似性查询 在微服务架构中,数据的高效存储与快速查询是至关重要的。Redis作为一个高性能的内存数据结构存储系统,不仅可以用作缓存、消息代理,还可以扩展为向量数据库,实现高效的相…...
设计模式-装饰者模式
背景 有一个咖啡馆有 单品咖啡:意大利浓咖啡、美式咖啡、无因咖啡 调料:牛奶、巧克力 点单时需要点一个单品咖啡,可以选择加调料或者不加。 最后计算价格。 较好的传统思路: 创建一个抽象的咖啡类,其中有各个调…...
.NetCore 过滤器和拦截器 的区别
Asp.NET Core 中的过滤器(Filter)和拦截器(Interceptor)是两个不同的概念,但它们在某些方面有相似之处,也有明显的区别。 🔑过滤器(Filter) 过滤器是Asp.NET Core中用于…...
uniapp实现APP版本升级
App.vue 直接上代码 <script>export default {methods: {//APP 版本升级Urlupload() {// #ifdef APP-PLUSplus.runtime.getProperty(plus.runtime.appid, (info) > {// 版本号变量持久化存储getApp().globalData.version info.version;this.ToLoadUpdate(info.versi…...
c语言的qsort函数理解与使用
介绍:qsort 函数是 C 标准库中用于排序的快速排序算法函数。它的用法非常灵活,可以对任意类型的元素进行排序,只要提供了比较函数即可。 qsort 函数原型及参数解释: void qsort ( void* base, //指向要排序的数组的首元素…...
k8s集群增加nfs-subdir-external-provisioner存储类
文章目录 前言一、版本信息二、本机安装nfs组件包三、下载nfs-subdir-external-provisioner配置文件并进行配置1.下载文件2.修改配置 三、进行部署备注:关于镜像无法拉取问题的处理 前言 手里的一台服务器搭建一个单点的k8s集群,然后在本机上使用nfs-su…...
IT成长之路-ubuntu驱动篇
历时3天的蹂躏,总结驱动安装全面教程。 步骤一、安装gcc、g和make包 #脚本更新 sudo apt-get update #编译gcc sudo apt-get install gcc #编译g sudo apt-get install g #编译make sudo apt-get install make 注意: gcc、g版本可能会导致显卡驱动安…...
AI大模型如何赋能电商行业,引领变革
目录 1.概述 1.1. 购物推荐系统 1.2. 会员分类与客户细分 1.3. 动态商品定价 1.4. 库存和供应链管理 1.5. 客户服务与体验 1.6. 内容生成与管理 2.AI技术在电商中的创新应用 2.1.淘宝 2.2.京东 2.3.华为 2.4.小米 3.AI技术在提高电商平台销售效率方面发挥的作用 …...
QT6学习第四天 感受QT的文件编译
QT6学习第四天 感受QT的文件编译 使用纯代码编写程序新建工程 使用其他编辑器纯代码编写程序并在命令行运行使用 .ui 表单文件生成界面使用自定义 C 窗口类使用现成的QT Designer界面类 使用纯代码编写程序 我们知道QT Creator中可以用拖拽的方式在 .ui 文件上布局,…...
地平线 bev_cft_efficientnetb3 参考算法-v1.2.1
01 概述 在自动驾驶感知算法中 BEV 感知成为热点话题,BEV 感知可以弥补 2D 感知的缺陷构建 3D “世界”,更有利于下游任务和特征融合。 地平线集成了基于 bev 的纯视觉算法,目前已支持 ipm-based 、lss-based、 transformer-basedÿ…...
【linux】shell脚本
文章目录 1. jar包启动脚本1.1 方式一1.2 方式二 2. 进程关闭脚本3. 操作mysql4. impala建表语句提取5. 监控磁盘存量6. 清日志脚本7. 替换tomcat的启动端口8. 将一行数据按照空格依次读取 1. jar包启动脚本 1.1 方式一 #!/bin/sh RESOURCE_NAME/usr/local/applications/scre…...
构建一个去中心化的零售生态参与者的商业模型
在数字化和去中心化技术快速发展的背景下,传统零售行业正迎来革命性的转型。去中心化零售生态不仅让消费者、商家和内容创作者在同一平台上共同参与价值的创造和分配,还推动了零售体验、数据控制和社会互动的彻底变革。本文将探讨如何构建一个去中心化的…...
Spring Boot开发实战:从入门到构建高效应用
Spring Boot 是 Java 开发者构建微服务、Web 应用和后端服务的首选框架之一。其凭借开箱即用的特性、大量的自动化配置和灵活的扩展性,极大简化了开发流程。本文将以实战为核心,从基础到高级,全面探讨 Spring Boot 的应用开发。 一、Spring B…...
MyBatis(mybatis_plus)中TypeHandler的使用教程
MyBatis(mybatis_plus)中TypeHandler的使用教程 一.TypeHandler作用及其使用场景 在我们平常开发操作数据库时,查询、插入数据等操作行为,有时会报数据类型不匹配异常,就可以得知数据的类型是不唯一的必然是多种不同…...
【C++】IO库(三):string流
8.3 string 流 sstream 头文件定义了三个类型来支持内存 IO,这些类型可以向 string 写入数据,也可以从 string 读取数据,就像 string 是一个 IO 流一样。 istringstream 从 string 读数据;ostringstream 向 string 写入数据&…...
C# 反射详解
反射是C#中的一个强大特性,允许程序在运行时检查和操作类型和对象的信息。 通过反射,你可以获取类型的属性、方法、构造函数等信息,并可以动态创建对象、调用方法或访问属性,甚至可以实现某些框架或库的核心功能。 反射的基本概念…...
量化交易系统开发-实时行情自动化交易-8.量化交易服务平台(一)
19年创业做过一年的量化交易但没有成功,作为交易系统的开发人员积累了一些经验,最近想重新研究交易系统,一边整理一边写出来一些思考供大家参考,也希望跟做量化的朋友有更多的交流和合作。 接下来会对于收集整理的33个量化交易服…...
【开发商城系统】
在广西开发商城系统,可以按照以下步骤进行: 确定项目需求:与客户沟通,了解商城系统所需的功能和特性,并确定项目的预算和时间限制。 进行市场调研:了解广西地区的电商市场情况,包括竞争对手、消…...
C++设计模式-享元模式
动机(Motivation) 在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作…...
Spark——安装步骤详细教程
1、安装步骤 1、上传 cd /opt/modules 2、解压 tar -zxf spark-3.1.2-bin-hadoop3.2.tgz -C /opt/installs 3、重命名 cd /opt/installs mv spark-3.1.2-bin-hadoop3.2 spark-local 4、创建软链接 ln -s spark-local spark 5、配置环境变量: vi /etc/prof…...
摆烂仙君传——深度学习秘境奇缘
第一章:深度学习秘境 在修仙界与科技交织的边缘,八荒六合九天无上摆烂仙君在其高科技修炼室中感应到一股神秘的召唤。这股力量似乎与他的灵魂产生了共鸣,引导他前往传说中的深度学习秘境。在那里,古老的仙法与前沿的算法交织&…...
C++设计模式:桥接模式(Bridge)
什么是桥接模式? 桥接模式(Bridge Pattern)是一个用来解耦的设计模式,它将抽象层和实现层分离开,让它们可以独立变化。用最简单的话来说,就是让你能够改变抽象的功能和具体的实现,而不需要修改…...
c++源码阅读__smart_ptr__正文阅读
文章目录 简介源码解析1. 引用计数的实现方式2. deleter静态方法的赋值时间节点3.make_smart的实现方式 与 好处4. 几种构造函数4.1 空构造函数4.2 接收指针的构造函数4.3 接收指针和删除方法的构造函数 , 以及auto进行模板lambda的编写4.4 拷贝构造函数4.5 赋值运算符 5. rele…...
halcon3D 1:1切片轮廓投影技术,透过像素距离,知实际物体的尺寸
首先说做个什么事儿 对一个物体的横截面进行1:1或者1:10的投影,也就是说世界物体1mm的话,投影到image中占1个或者10个像素值,这样,就可以透过直接计算image中的像素距离,知道实际物体的尺寸 用一张图说明是这样的。物…...
npm库xss依赖的使用方法和vue3 中Web富文本编辑器 wangeditor 使用xss库解决 XSS 攻击的方法
npm库xss依赖的使用方法和vue3 中Web富文本编辑器 wangeditor 使用xss库解决 XSS 攻击的方法 1. npm库xss依赖的使用方法1.1 xss库定义1.2 xss库功能 2. vue3 中 wangeditor 使用xss库解决 XSS 攻击的方法和示例2.1 在终端执行如下命令安装 xss 依赖2.2 在使用 wangeditor 的地…...