动态规划的优化

news2024/11/15 5:16:06

动态规划的优化

一、空间优化

说明

动态规划空间优化为滚动数组优化,即对于一个多维数组,转移时均是由上一阶段转移来的,则可以将这一维省略,以降低空间复杂度,但要注意转移时的顺序;

例题

0 - 1 背包问题

题目

有一个最多能装 m m m 千克的背包,有 n n n 件物品,它们的重量分别是 W 1 , W 2 , . . . , W n W_1,W_2,..., W_n W1W2...,Wn ,它们的价值分别是 C 1 , C 2 , . . . , C n C_1,C_2,... ,C_n C1C2...Cn

若每种物品只有一件,问能装入的最大总价值;

分析

状态

由于最终价值与物品与重量有关,所以可定义状态, d p [ i ] [ j ] dp[i][j] dp[i][j] 表示前 i i i 件物品装在容量为 j j j 的背包中所能装入的最大总价值;

转移

依次遍历每一个物品与背包容量,比较取与不取当前物品的价值;

状态转移方程

d p [ i ] [ j ] = max ⁡ { d p [ i − 1 ] [ j ]    ( j < w [ i ] ) d p [ i − 1 ] [ j − w [ i ] ] + c [ i ] dp[i][j] = \max \begin{cases} dp[i- 1][j] \; (j < w[i]) \\ dp[i - 1][j - w[i]] + c[i] \end{cases} dp[i][j]=max{dp[i1][j](j<w[i])dp[i1][jw[i]]+c[i]

优化

d p [ i ] [ j ] dp[i][j] dp[i][j] 转移时,对于枚举物品这一维只用了 i i i i − 1 i - 1 i1 两个状态,在数组中即为,

dp j − w [ i ] j - w[i] jw[i] j j j
i − 1 i - 1 i1 d p [ i − 1 ] [ j − w [ i ] ] dp[i - 1][j - w[i]] dp[i1][jw[i]] d p [ i − 1 ] [ j ] dp[i - 1][j] dp[i1][j]
i i i d p [ i ] [ j ] dp[i][j] dp[i][j]

即在 d p [ i ] [ j ] dp[i][j] dp[i][j] 的转移中,均是通过 d p [ i − 1 ] dp[i - 1] dp[i1] 这一维的状态转移过来的,则转移时只保存上一阶段的所有状态和当前阶段的所有状态即可,再利用这两个数组不断滚动计算,则可以得到最后一阶段的最后一个状态;

既可以优化为,

d p [ j ] dp[j] dp[j]:容量为 j j j 的背包装下物品的价值的最大值;

但在计算 d p [ j ] dp[j] dp[j] 时,需要用到 d p [ j − w [ i ] ] dp[j - w[i]] dp[jw[i]] ,如果 j j j 从小到大枚举,则 d p [ j − w [ i ] ] dp[j - w[i]] dp[jw[i]] 则为当前状态 i i i 的,不是 i − 1 i - 1 i1 的状态,所以 j j j 应从大到小枚举;

依次遍历每一个物品与背包容量,比较取与不取当前物品的价值;

状态转移方程

$ dp[j] = \max {dp[j], dp[j - w[i]] + c[i] } $

代码

#include <cstdio>
#include <algorithm>
#define MAXN 20
#define MAXX 105
using namespace std;
int n, v, w[MAXN], c[MAXN], dp[MAXX];
int main() {
	scanf("%d %d", &n, &v);
	for (int i = 1; i <= n; i++) {
		scanf("%d %d", &w[i], &c[i]);
	}
	for (int i = 1; i <= n; i++) { // 遍历物品
		for (int j = v; j >= w[i]; j--) { // 反向枚举
			dp[j] = max(dp[j], dp[j - w[i]] + c[i]); // 状态转移
		}
	}
	printf("%d", dp[v]);
	return 0;
} 

二、单调队列优化

说明

单调队列就是队内元素保持一定单调性的队列,即从队首到队尾单调递增或递减的队列;

可借助单调队列的单调性及时排除不可能的决策,保持候选集合的有效性与秩序性;

即对于形如 d p [ i ] = max ⁡ j = a ( a < i ) i − 1 { d p [ j ] + x ( i , j ) } dp[i] = \max_{j = a(a < i)}^{i - 1}\{dp[j] + x(i, j)\} dp[i]=maxj=a(a<i)i1{dp[j]+x(i,j)} 的状态转移方程,可使用单调队列优化,维护一个单调递增或递减的单调队列,将 d p dp dp 数组全部存入单调队列中;

但为了方便判断单调队列中的状态是否满足 j j j 的范围,一般在单调队列中存储下标;

对于 d p [ i ] dp[i] dp[i] 更新时,先将单调队列中不满足 j j j 的范围的状态从队列中删除,再利用单调队列的单调性选出对于 d p [ i ] dp[i] dp[i] 的最优 d p [ j ] dp[j] dp[j] ,用其更新 d p [ i ] dp[i] dp[i] ,再将 d p [ i ] dp[i] dp[i] 存入队列中继续更新;

例题

Mowing the Lawn G

题目

N ( 1 ≤ N ≤ 1 0 5 ) N (1 \leq N \leq 10^5) N(1N105) 只奶牛,已知每只奶牛的效率 E i E_i Ei ,选取一种方案,使该方案中没有连续的超过 K 只奶牛且奶牛的效率总和最大;

分析

状态

由于要求不能有连续 K K K 只奶牛存在,所以定义状态为,

d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1] 表示前 i i i 只奶牛选 (1) 与不选 (0) ;

转移

对于第 i i i 只奶牛,

若不选第 i i i 只,则比较前 i − 1 i - 1 i1 只中第 i − 1 i - 1 i1 只选与不选的最大值即可;

若选第 i i i 只,则枚举 j ( i − k ≤ j < i ) j (i - k \leq j < i) j(ikj<i) ,选取 j ∼ i j \sim i ji 这一区间的奶牛;

状态转移方程即为,
d p [ i ] [ 0 ] = max ⁡ { d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] } d p [ i ] [ 1 ] = max ⁡ j = i − k i − 1 { d p [ j ] [ 0 ] − s u m [ j ] + s u m [ i ] } dp[i][0] = \max\{dp[i - 1][0], dp[i - 1][1]\} \\ dp[i][1] = \max_{j = i - k}^{i - 1}\{dp[j][0] − sum[j] + sum[i]\} dp[i][0]=max{dp[i1][0],dp[i1][1]}dp[i][1]=j=ikmaxi1{dp[j][0]sum[j]+sum[i]}
时间复杂度为 O ( N ∗ N ) O(N * N) O(NN) ,考虑优化;

对于 d p [ i ] [ 1 ] dp[i][1] dp[i][1] 的方程,可将 s u m [ i ] sum[i] sum[i] 提出,得 d p [ i ] [ 1 ] = max ⁡ j = i − k i − 1 { d p [ j ] [ 0 ] − s u m [ j ] } + s u m [ i ] } dp[i][1] = \max_{j = i - k}^{i - 1}\{dp[j][0] − sum[j]\} + sum[i]\} dp[i][1]=maxj=iki1{dp[j][0]sum[j]}+sum[i]} ,则可使用单调队列优化,维护一个递减单调队列;

依次遍历 n n n 个物品,若当前物品编号为 i i i 则,

先更新 d p [ i ] [ 0 ] dp[i][0] dp[i][0] 的值;

将单调队列存储的候选优解中下标不满足 j j j 范围的从单调队列中删除;

用单调队列的队首元素更新 d p [ i ] dp[i] dp[i] 的值;

将下标 i i i 存入单调队列中,但为维护单调队列的单调性,应先将单调队列队尾元素中 d p dp dp 值小于 d p [ i ] dp[i] dp[i] 的元素从队列中删除,再将下标 i i i 存入单调队列;

代码

#include <cstdio>
#include <algorithm>
#define MAXN 100005
using namespace std;
int n, k;
long long a[MAXN], sum[MAXN], dp[MAXN][2];
int q[MAXN], head = 1, tail = 1; // 单调队列
int main() {
	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &a[i]);
		sum[i] = sum[i - 1] + a[i]; // 计算前缀和
	}
	for (int i = 1; i <= n; i++) {
		dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]); // 更新 DP
		while (head <= tail && q[head] < i - k)	head++; // 去除单调队列中已无效的状态
		dp[i][1] = dp[q[head]][0] - sum[q[head]] + sum[i]; // 更新 DP
		while (head <= tail && dp[q[tail]][0] - sum[q[tail]] < (dp[i][0] - sum[i])) tail--; //维持点调性
		q[++tail] = i; // 存入新状态
	}
	printf("%lld", max(dp[n][0], dp[n][1]));
	return 0;
}

总结

更为一般地,对于可以单调队列优化的状态转移式均可写为以下形式,
d p [ i ] = min ⁡ j = L ( i ) R ( i ) { d p [ j ] + v a l ( i , j ) } dp[i] = \min_{j = L(i)}^{R(i)}\{dp[j] + val(i, j)\} dp[i]=j=L(i)minR(i){dp[j]+val(i,j)}
此为动态规划的一类模型,被称为 1D/1D 的动态规划;

其中,

L ( i ) , R ( i ) L(i), R(i) L(i),R(i) 为关于 i i i 的一次函数,且有 R ( i ) ≤ i R(i) \leq i R(i)i ,限制了 j j j 的决策范围,保证其上下界变化具有单调性;

v a l ( i , j ) val(i, j) val(i,j) 为关于 i , j i, j i,j 的多项式函数;

回顾上题,将 v a l ( i , j ) = q ( i ) + p ( j ) val(i, j) = q(i) + p(j) val(i,j)=q(i)+p(j) 拆为了两个部分,一部分 q ( i ) q(i) q(i) 仅与 i i i 有关,另一部分 p ( j ) p(j) p(j) 仅与 j j j 有关,将 q ( i ) q(i) q(i) 提出 min ⁡ j = L ( i ) R ( i ) { } \min_{j = L(i)}^{R(i)}\{\} minj=L(i)R(i){} 中,用单调队列维护 d p [ j ] + p ( j ) dp[j] + p(j) dp[j]+p(j) 的值;

所以在上述 1D/1D 的动态规划中,多项式 v a l ( i , j ) val(i, j) val(i,j) 是否能且仅能拆分为存在 q ( i ) , p ( j ) q(i), p(j) q(i),p(j) 两个部分是能否使用单调队列优化的基本条件;

d p dp dp 状态转移方程形如 d p [ i ] = min ⁡ j = L ( i ) R ( i ) { d p [ j ] + q ( i ) + p ( j ) } dp[i] = \min_{j = L(i)}^{R(i)}\{dp[j] + q(i) + p(j)\} dp[i]=minj=L(i)R(i){dp[j]+q(i)+p(j)} 可用单调队列优化;

三、斜率优化

说明

在 1D/1D 的动态规划中,多项式 v a l ( i , j ) val(i, j) val(i,j) 若能拆分成 q ( i ) + p ( j ) + a ( i ) ∗ b ( j ) q(i) + p(j) + a(i) * b(j) q(i)+p(j)+a(i)b(j) 即可以使用动态规划的斜率优化;

其中, q ( i ) , a ( i ) q(i), a(i) q(i),a(i) 仅与 i i i 有关, p ( j ) , b ( j ) p(j), b(j) p(j),b(j) 仅与 j j j 有关;

d p dp dp 状态转移方程形如 d p [ i ] = min ⁡ j = L ( i ) R ( i ) { d p [ j ] + q ( i ) + p ( j ) + a ( i ) ∗ b ( j ) } dp[i] = \min_{j = L(i)}^{R(i)}\{dp[j] + q(i) + p(j) + a(i) * b(j)\} dp[i]=minj=L(i)R(i){dp[j]+q(i)+p(j)+a(i)b(j)} 可用斜率优化;

即可继续方程式变形,
d p [ i ] = d p [ j ] + q ( i ) + p ( j ) + a ( i ) ∗ b ( j ) d p [ j ] + p ( j ) = − a ( i ) ∗ b ( j ) + d p [ i ] + q ( i ) \begin{aligned} dp[i] &= dp[j] + q(i) + p(j) + a(i) * b(j) \\ dp[j] + p(j) &= -a(i) * b(j) + dp[i] + q(i) \\ \end{aligned} dp[i]dp[j]+p(j)=dp[j]+q(i)+p(j)+a(i)b(j)=a(i)b(j)+dp[i]+q(i)
变形为 y = k x + b y = kx + b y=kx+b 的样式,其中 d p [ j ] + p ( j ) dp[j] + p(j) dp[j]+p(j) 即为 y y y b ( j ) b(j) b(j) 即为 x x x − a ( i ) -a(i) a(i) 即为 k k k d p [ i ] + q ( i ) dp[i] + q(i) dp[i]+q(i) 即为 b b b

则平面直角坐标系的一个点 ( b ( j ) , d p [ j ] + p ( j ) ) (b(j), dp[j] + p(j)) (b(j),dp[j]+p(j)) 仅与 j j j 有关,整个 d p dp dp 是一条直线,其斜率为 − a ( i ) -a(i) a(i) ,截距为 d p [ i ] + q ( i ) dp[i] + q(i) dp[i]+q(i) ,由于要求 d p [ i ] dp[i] dp[i] 最小,则应让一条过点 ( b ( j ) , d p [ j ] + p ( j ) ) (b(j), dp[j] + p(j)) (b(j),dp[j]+p(j)) 的直线截距 d p [ i ] + q ( i ) dp[i] + q(i) dp[i]+q(i) 最小;

由于在求解 d p [ i ] dp[i] dp[i] 值时, − a ( i ) -a(i) a(i) 仅与 i i i 有关,所以可以将其看作一个定值;

即求过点 ( b ( j ) , d p [ j ] + p ( j ) ) (b(j), dp[j] + p(j)) (b(j),dp[j]+p(j)) 的斜率为 − a ( i ) -a(i) a(i) 的直线的截距 d p [ i ] + q ( i ) dp[i] + q(i) dp[i]+q(i) 最小;

若图上的每个点均为一个 j j j 所对应的点,直线为 l l l ,则此时情况为,

斜率优化说明-C-1

则点 C C C 即为 d p [ i ] dp[i] dp[i] 对应的最优的 d p [ j ] dp[j] dp[j]

则此时可以发现, A , B , C A, B, C A,B,C 三个点共同组成了一个下凸包,即 K l ( A , C ) < K l ( C , B ) K_{l(A, C)} < K_{l(C, B)} Kl(A,C)<Kl(C,B) ,则中间点 C C C 即为最优解;

对于剩下的两个点,

对于 A A A 点,由于斜率不断增大, A A A点不可能用来转移后面的状态,所以将它删除;
对于 B B B 点,当斜率到达一定大小,例如下图,

斜率优化说明-B-2

此时最优解为 B B B ,而 C C C 又要删除;

所以只要维护一个下凸包,使得下凸包中相邻两个点连的斜率要大于当前这条线的斜率,正如上例;

可以使用单调队列维护,

一旦最左端的一个点和次左端的点的连线要小于当前的斜率了,就把最左端的点删除,每次遇到新的直线,直接拿最左端的点来转移;

加入一个新点 i i i 就加到最右边,由于横坐标也是递增的,在加入点 i i i 之前,一定要保证下凸的性质,先将 i i i 点与单调队列队尾元素组成直线 l 1 l_1 l1 的斜率与单调队列队尾两个元素组成的直线 l 2 l_2 l2 的斜率相比较;

如下图所示,

斜率优化说明-队尾维护-3

K l 1 K_{l_1} Kl1 大于 K l 2 K_{l_2} Kl2 ,则队尾元素一定不会成为最优解,则将队尾元素删除 ,再将下标 i i i 存入单调队列;

注意,比较斜率时,为防止卡精度可十字相乘转化为乘积形式,但若分母为负数,应该要变号;

例题

玩具装箱

题目

n n n 个数,每个数有一个值 C i C_i Ci ,将这 n n n 个数分为若干段,对于一段 i ∼ j i \sim j ij ,其的费用为 ( j − i + ∑ k − i j C k − L ) 2 (j - i + \sum_{k - i}^{j} C_k - L)^2 (ji+kijCkL)2 ,求最小的总费用;

分析

状态

d p [ i ] dp[i] dp[i] 表示前 i i i 个数总费用的最小值;

转移

通过题目费用计算方法可知状态转移方程为,
d p [ i ] = min ⁡ j = 1 i − 1 { d p [ j ] + ( i − j − 1 + s u m [ i ] − s u m [ j ] − L ) 2 } dp[i] = \min_{j = 1}^{i - 1}\{dp[j] + (i - j - 1 + sum[i] − sum[j] − L)^2\} dp[i]=j=1mini1{dp[j]+(ij1+sum[i]sum[j]L)2}

优化

先转化状态转移方程,
d p [ i ] = d p [ j ] + ( i − j − 1 + s u m [ i ] − s u m [ j ] − L ) 2 d p [ i ] = d p [ j ] + ( ( i − s u m [ i ] ) − ( s u m [ j ] + j − L − 1 ) ) 2 \begin{aligned} dp[i] & = dp[j] + (i - j - 1 + sum[i] − sum[j] − L)^2 \\ dp[i] & = dp[j] + ((i - sum[i]) - (sum[j] + j − L - 1))^2 \\ \end{aligned} dp[i]dp[i]=dp[j]+(ij1+sum[i]sum[j]L)2=dp[j]+((isum[i])(sum[j]+jL1))2
为方便表示,令 A [ i ] = i + s u m [ i ] , B [ j ] = j + s u m [ j ] − L − 1 A[i] = i + sum[i], B[j] = j + sum[j] - L - 1 A[i]=i+sum[i],B[j]=j+sum[j]L1 ,即
d p [ i ] = d p [ j ] + ( A [ i ] − B [ j ] ) 2 d p [ i ] = d p [ j ] + A [ i ] 2 + B [ j ] 2 − 2 ∗ A [ i ] ∗ B [ j ] d p [ j ] + B [ j ] 2 = 2 ∗ A [ i ] ∗ B [ j ] + d p [ i ] − A [ i ] 2 \begin{aligned} dp[i] & = dp[j] + (A[i] - B[j])^2 \\ dp[i] & = dp[j] + A[i]^2 + B[j]^2 - 2 * A[i] * B[j] \\ dp[j] + B[j]^2 &= 2 * A[i] * B[j] + dp[i] - A[i]^2 \end{aligned} dp[i]dp[i]dp[j]+B[j]2=dp[j]+(A[i]B[j])2=dp[j]+A[i]2+B[j]22A[i]B[j]=2A[i]B[j]+dp[i]A[i]2
其中 d p [ j ] + B [ j ] 2 dp[j] + B[j]^2 dp[j]+B[j]2 即为 y y y 2 ∗ A [ i ] 2 * A[i] 2A[i] 即为 k k k B [ j ] B[j] B[j] 即为 x x x d p [ i ] + A [ i ] 2 dp[i] + A[i]^2 dp[i]+A[i]2 即为 b b b

即求过 ( B [ j ] , d p [ j ] + B [ j ] 2 ) (B[j], dp[j] + B[j]^2) (B[j],dp[j]+B[j]2) ,斜率为 2 ∗ A [ i ] 2 * A[i] 2A[i] 的直线的截距的最小值;

即可通过单调队列维护一个下凸包;

先预处理出 A , B , s u m A, B, sum A,B,sum 数组;

再依次遍历每一个数,

先将队头两个点组成直线的斜率与 2 ∗ A [ i ] 2 * A[i] 2A[i] 比较,若队头两个点组成直线的斜率比 2 ∗ A [ i ] 2 * A[i] 2A[i] 小,则不能去,将其从对头删除;

用单调队列的队首元素更新 d p [ i ] dp[i] dp[i] 的值;

将下标 i i i 存入单调队列中,但为维护下凸包斜率的单调性,先将 i i i 点与单调队列队尾元素组成直线 l 1 l_1 l1 的斜率与单调队列队尾两个元素组成的直线 l 2 l_2 l2 的斜率相比较;

K l 1 K_{l_1} Kl1 应大于 K l 2 K_{l_2} Kl2 ,否则则 i i i 一定不会成为最优解则将队尾元素删除 ,再将下标 i i i 存入单调队列;

代码

#include <cstdio>
#include <algorithm>
#define MAXN 500005
using namespace std;
int n;
long long l, c[MAXN], sum[MAXN], dp[MAXN], a[MAXN], b[MAXN];
int head, tail, q[MAXN];
long long get_up(int x, int y) { // y 坐标差值
	return dp[x] + b[x] * b[x] - dp[y] - b[y] * b[y];
}
long long get_down(int x, int y) { // x 坐标差值
	return b[x] - b[y];
}
long long get_dp(int i, int j) { // 获取 dp 值
	return dp[j] + (a[i] - b[j]) * (a[i] - b[j]);
}
int main() {
	scanf("%d %lld", &n, &l);
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &c[i]);
		sum[i] = sum[i - 1] + c[i]; // 预处理
		a[i] = sum[i] + i;
		b[i] = sum[i] + i + l + 1;
	}
	b[0] = l + 1;
	head = tail = 1; // 清空队列
	for (int i = 1; i <= n; i++) {
		while (head < tail && get_up(q[head + 1], q[head]) < 2 * a[i] * get_down(q[head + 1], q[head])) head++; // 通过斜率维护下凸
		dp[i] = get_dp(i, q[head]); // 更新 DP 值
		while (head < tail && get_up(i, q[tail]) * get_down(q[tail], q[tail - 1]) < get_down(i, q[tail]) * get_up(q[tail], q[tail - 1])) tail--; // 维护将 i 节点加入队列后的下凸
		q[++tail] = i; // 存入新的节点
	}
	printf("%lld\n", dp[n]);
	return 0;
}

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

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

相关文章

基础算法--背包问题(01背包问题、完全背包问题、多重背包问题、分组背包问题)

文章目录前言01背包问题完全背包问题多重背包问题分组背包问题前言 背包问题&#xff1a;给我们 i 件物品&#xff0c;每件物品都有体积 vi 和权重 wi &#xff0c;给我们限制条件&#xff0c;让我们选择在背包的容量内&#xff0c;物品达到权重最大 01背包问题 01背包问题描…

KK集团再冲刺港交所上市:期内被罚款30万元,曾存在“二清”问题

时隔一年&#xff0c;KK集团再次在港交所递交上市申请。2023年1月20日&#xff0c;KK集团&#xff08;KK Group Company Holdings Limited&#xff09;向港交所提交上市申请。据贝多财经了解&#xff0c;KK集团曾于2021年11月4日在港交所递表&#xff0c;后已“失效”。 相较于…

LeetCode_单周赛_329

2544. 交替数字和 代码1 转成字符串&#xff0c;逐个判断 class Solution {public int alternateDigitSum(int n) {char[] s ("" n).toCharArray();int t 1;int ans 0;for (int i 0; i < s.length; i) {ans (s[i] - 0) * t;t -t;}return ans;} }代码2 一…

国内做SaaS软件的知名企业有哪些?

SaaS厂商还挺多挺杂的。具体要列举的话&#xff0c;还是按照分类来吧。 通用业务和垂直行业的SaaS 对使用方来说&#xff0c;一般分为业务通用型和垂直行业型。 通用型是可以服务所有企业的&#xff0c;比如CRM&#xff08;客户管理软件&#xff09;、HR软件、协同办公软件&a…

linux系统中利用QT实现语音识别项目的操作方法

大家好&#xff0c;今天主要和大家分享一下&#xff0c;如何使用linux系统上的语音识别项目的操作方法与实现。 目录 第一&#xff1a;语音识别基本简介 第二&#xff1a;语音识别产品申请账号 第三&#xff1a;具体代码实现 第一&#xff1a;语音识别基本简介 AI音箱对传统…

Java_Git:3. 远程仓库

目录 1 添加远程库 1.1 在github上创建仓库 1.2 ssh协议 1.2.1 什么是ssh? 1.2.2 基于密匙的安全验证 1.2.3 ssh密钥生成 ​​​​​​​​​​​​​​1.2.4 ssh密钥配置 1.3 同步到远程仓库 1.3.1 使用git bash 1.3.2 使用TortoiseGit同步 2 从远程仓库克隆 2.1 …

CSS颜色:RGB颜色/HEX颜色/HSL颜色(网页颜色完全总结)

目录 CSS 颜色名 CSS 背景色 实例 CSS 文本颜色 ​编辑 实例 CSS 边框颜色 实例 CSS 颜色值 实例 RGB 值 rgb(red, green, blue) 实例 实例 RGBA 值 rgba(red, green, blue, alpha) 实例 HEX 值 #rrggbb 实例 实例 HSL 值 hsla(hue, saturation, lightn…

autojs模仿QQ长按弹窗菜单

牙叔教程 简单易懂 分析弹框菜单 圆角列表, 类似grid箭头位于文字中间上(下)方需求分析 如果要写一个这样的教程, 我们需要做什么 写一个列表, 用来触发长按选项写一个弹窗菜单代码分析 列表怎么写, 先来一个最简单的布局代码 "nodejs ui"; require("rhin…

系统架构:分层架构

引子 系统在从0到1阶段时&#xff0c;为了可让产品快速上线&#xff0c;此时系统分层一般不是软件开发需要重点考虑的范畴&#xff0c;但是随着业务逐渐复杂 &#xff0c;大量代码纠缠耦合&#xff0c;此时会出现逻辑不清楚、模块相互依赖、扩展性差、改一处动全身的问题。 系…

基于双层共识控制的直流微电网优化调度(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f389;作者研究&#xff1a;&#x1f3c5;&#x1f3c5;&#x1f3c5;本科计算机专业&#xff0c;研究生电气学硕…

14. python运算符

Python 语言支持以下类型的运算符 1. 算术运算符 、-、*、/、%、**、// **  返回x的y次幂 //  取整除 - 向下取接近商的整数(//得到的并不一定是整数类型的数&#xff0c;它与分母分子的数据类型有关系) print(7//2) print(7.0//2) print(7//2.0)2. 比较&#xff08;关系&…

进程概念——Linux

“技术是时间积淀出来的&#xff0c;你能速成的东西&#xff0c;别人也可以速成,所以需要耐心学习” 猛戳订阅&#x1f341;&#x1f341; &#x1f449;Linux操作系统详解&#x1f448; &#x1f341;&#x1f341; 这里是目录标题一、冯诺依曼结构为什么要存在内存&#xff1…

关系数据库-1-[mysql8]中的数据类型

详细介绍MySQL中的数据类型 1 MySQL中的数据类型 常见数据类型的属性&#xff0c;如下&#xff1a; 1.1 整数类型 一、类型介绍 整数类型一共有5种&#xff0c;包括TINYINT、SMALLINT、MEDIUMINT、INT(INTEGER)和 BIGINT。 二、可选属性 1、M:表示显示宽度 Q&#xff1a;…

【2022】年度总结——彼此当年少 莫负好时光

文章目录【2022】年度总结前言&#x1f388;&#x1f388;&#x1f388;2022的得与失&#x1f9e8;&#x1f9e8;&#x1f9e8;对2023的期望&#x1f4e7;&#x1f4e7;&#x1f4e7;写在最后的话✍&#x1f3fb;✍&#x1f3fb;✍&#x1f3fb;【2022】年度总结 前言&#x1f…

client-go实战之七:准备一个工程管理后续实战的代码

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 系列文章链接 client-go实战之一&#xff1a;准备工作client-go实战之二:RESTClientclient-go实战之三&#xff1a;Clientsetclient-go实战之四&#xff1a;…

TCP为什么是三次握手和四次挥手以及可能出现的问题

目录TCP为啥设定为三次握手(两个角度分析)不可靠产生无效链接浪费服务器资源TCP为啥四次挥手服务端有剩余数据需要发送--四次挥手(多数情况)服务端无剩余数据发送--捎带应答--四次变三次(少数情况)四次挥手可能出现的问题可能出现大量的TIME_WAIT可能出现大量的CLOSE_WAITTCP为…

关于他人交谈?顺应张莉打破预期

如果你站在权利的优势场,其实你不用可以谋划什么,就可以直接顺利交流.这个时候打破预期,就要对别人更加尊重.例子&#xff1a; 美国前总统克林顿跟每一个在场的人员握手并询问名字。交流中弱势一方的预期是在&#xff0c;希望得到对方尊重&#xff0c;而不是工具人。如果站在劣…

文件没学懂没关系,我来教你快速学会文件

1. 什么是文件 文件通常是在磁盘或固态上的一段已经命名的存储区。C把文件看作是一系列连续的字节&#xff0c;每个字节都被单独读取。 在程序设计中&#xff0c;我们一般谈的文件有两种&#xff1a;程序文件、数据文件&#xff08;从文件功能的角度来分类的&#xff09; 1.…

Spring Boot操作数据库学习之整合MyBatis

文章目录一 MyBatis简介二 配置数据源三 整合测试3.1 导入MyBatis依赖3.2 配置数据库连接信息application.yml3.3 使用idea测试数据库3.4 创建实体类【可以使用Lombok】3.5 创建实体类3.6 创建mapper目录以及对应的Mapper接口3.7 创建Mapper映射文件3.8 配置mybatis映射文件3.9…

第四十四章 动态规划——背包问题模型(一)

第四十四章 动态规划——背包问题模型&#xff08;一&#xff09;一、模型概述二、模型变形1、AcWing 423. 采药&#xff08;1&#xff09;问题&#xff08;2&#xff09;分析&#xff08;3&#xff09;代码2、AcWing 1024. 装箱问题&#xff08;1&#xff09;问题&#xff08;…