当前位置: 首页 > news >正文

动态规划入门

前言:首先,什么是动态规划?

      动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。

      我们都熟知的斐波那切数列问题就是典型的动态规划问题,后面的问题的解,与前面已经求出来的问题的解有关,也就是我们经常在递归中用公式   f[i]=f[i-1]+f[i-2](i>2),在动态规划中,我们也把这种类型的公式叫做状态转移方程。

      我们的动态规划算法,本质上是由dfs而来,经历了dfs->记忆化搜索->动态规划的过程,可以说,动态规划就是dfs的提高。

1.典例引入:

爬楼梯(斐波那切数列的应用)

 这就是典型的斐波那切数列问题,我们跳到第i级台阶有两种可行方案,第一种是从第i-1级台阶上跳一步,另一种是从第i-2级台阶跳两步,而第i-1级台阶和第i-2级台阶也分别可以由两种不同的方案,当然我们需要知道前两个初始值,以便让我们开始循环求解方案数,而我们易知第一级台阶只有一种方案,第二节台阶有两种方案,从第三极台阶开始我们就可以通过递归来求解了,当然,这个例子想必自然不用多说,但凡学过递归的,肯定都是老生常谈的例子了,这里直接给出代码,给后续的例题提供模板。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 20;
int n;
int dfs(int n)
{if (n == 1)return 1;else if (n == 2)return 2;elsereturn  dfs(n - 1) + dfs(n - 2);
}
int main()
{cin >> n;cout << dfs(n) << endl;return 0;
}

1.1从dfs到记忆化搜索再到动态规划的优化算法

上面的斐波那切数列数列式的问题,在数据不大的前提下我们的dfs是可行的,但是,我们知道dfs的执行过程实际上是极为复杂的,这中间多次重复的调用已经求出的值,我们可以进一步优化算法,把子问题的答案存起来,去掉重复值;

1.1.1 记忆化搜索

所谓记忆化搜索,就是将已经求出的子问题的答案保存在数组中,当我们在求解一个问题是,先查找数组中是否已有答案,查到直接返回数组值,没查到再进行递归求解,这样可以省去重复的分支,优化时间复杂度。(这里不考虑数据溢出的问题,事实上,当我们的n为50的时候就已经爆int了~~

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int n;
int mem[maxn];
int dfs(int n)
{if (mem[n])return mem[n];int sum = 0;if (n == 1)sum = 1;else if (n == 2)sum = 2;elsesum = dfs(n - 1) + dfs(n - 2);mem[n] = sum;return sum;
}
int main()
{cin >> n;memset(mem, 0, sizeof(mem));cout << dfs(n) << endl;return 0;
}

1.1.2 动态规划

我们的动态规划实际上就是记忆化搜索的改进,本质上还是递归,递(把一个大问题分解成一个个子问题,相当于自顶向下求解)归(由最小子问题答案带回求出大问题答案,相当于自底向上返回大问题答案),动态规划,就是省去“递”的过程,直接从已知子问题开始,逐步求解大问题,直到求出大问题的解。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int n;
int f[maxn];//sum = dfs(n - 1) + dfs(n - 2);int main()
{cin >> n;f[1] = 1;f[2] = 2;if(n==1||n==2){cout<<n<<endl;return 0;}for (int i = 3; i <= n; i++)f[i] = f[i - 1] + f[i - 2];cout << f[n] << endl;return 0;
}

*1.1.3三变量的再优化(空间复杂度的优化)

在上述的递推过程中我们不难发现,f[i]的取值只和f[i-1]还有f][i-2]有关,我们可以直接用三个变量来代替整个数组来优化空间,这个并不难能想到,这里只是一提,事实上,在一些竞赛等方面,时间复杂的才是更重要的考察点。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int n;
int ans = 0;
int main()
{cin >> n;if (n == 1 || n == 2){cout << n << endl;return 0;}int f1 = 1, f2 = 2;for (int i = 3; i <= n; i++){ans = f1 + f2;f1 = f2;f2 = ans;}cout << ans << endl;return 0;
}

2.渐入佳境

相信你可能已经跃跃欲试了,这不就来了嘛

 

 这个题可能刚开始并不容易想到思路,因为这并不像前面的爬楼梯一样是简单的方案数相加问题了,这是一道求最优解的问题,我们来捋下思路,

那我,我们现在就可以很容易的写出dfs版的代码:

#include <bits/stdc++.h>using namespace std;
const int maxn = 1e5 + 5;
int T,n;
int ans = 0;
int w[maxn];//表示店铺的价值
int dfs(int x)//x表示第x家店铺
{if (x > n)return 0;elsereturn max(dfs(x + 1), dfs(x+2) + w[x]);//x+1表示第x家店铺不选,那么这家店铺的价值就肯定得不到了,x+2表示选择第x+2加店铺,说明选择了第x家店铺
}
int main()
{cin >> T;while (T--){cin >> n;for (int i = 1; i <= n; i++)cin >> w[i];int ret=dfs(1);cout << ret << endl;}return 0;
}

上面的代码很存在很多的重复性的子分支存在,很遗憾的,这段代码会TLE的,那我在我们之前的优化中,就要采用记忆化搜索和动态规划来优化时间了,

2.1.记忆化搜索改进

#include <bits/stdc++.h>using namespace std;
const int maxn = 1e5 + 5;
int T,n;
int ans = 0;
int w[maxn];//表示店铺的价值
int mem[maxn];
int dfs(int x)//x表示第x家店铺
{if (mem[x])return mem[x];int sum = 0;if (x > n)sum = 0;elsesum= max(dfs(x + 1), dfs(x+2) + w[x]);//x+1表示第x家店铺不选,那么这家店铺的价值就肯定得不到了,x+2表示选择第x+2加店铺,说明选择了第x家店铺mem[x] = sum;return sum;
}
int main()
{cin >> T;while (T--){memset(mem, 0, sizeof(mem));cin >> n;for (int i = 1; i <= n; i++)cin >> w[i];int ret=dfs(1);cout << ret << endl;}return 0;
}

2.2动态递归

我们在一般的竞赛中,记忆化数组还是不常用的,事实上,上一个题的记忆化搜索已经可以AC了,我们还是来搞一下比较常用的动态规划

#include <bits/stdc++.h>using namespace std;
const int maxn = 1e5 + 5;
int T,n;
int w[maxn];//表示店铺的价值
int f[maxn];//max(dfs(x + 1), dfs(x+2) + w[x]);//x+1表示第x家店铺不选,那么这家店铺的价值就肯定得不到了,x+2表示选择第x+2加店铺,说明选择了第x家店铺int main()
{cin >> T;while (T--){memset(f, 0, sizeof(f));cin >> n;for (int i = 1; i <= n; i++)cin >> w[i];for (int i = n; i >= 1; i--){f[i] = max(f[i+1], f[i + 2] + w[i]);//由底层求到根节点}cout << f[1] << endl;}return 0;
}

很多人可能不理解为什么要逆序来进行递推,说实话,一开始我也不太理解,但是我们来看,在上面的二叉树类型的结构中,我们需要根据上面所求得的答案来推出下面的最优解,也就是相当于最小的已知子问题是我先把第一个元素作为条件开始进行递归的,第一个子问题的答案我们是知道的,动态规划的本质就是从大的未知问题向小的已知的子问题的“归”操作,并且我们的递归过程一定是从大问题到小问题的“回溯”过程中才能得出答案的,假如我们用的是正序,那么状态转移方程就要变变形式了。

#include <bits/stdc++.h>using namespace std;
const int maxn = 1e5 + 5;
int T,n;
int w[maxn];//表示店铺的价值
int f[maxn];//max(dfs(x + 1), dfs(x+2) + w[x]);//x+1表示第x家店铺不选,那么这家店铺的价值就肯定得不到了,x+2表示选择第x+2加店铺,说明选择了第x家店铺int main()
{cin >> T;while (T--){memset(f, 0, sizeof(f));cin >> n;for (int i = 1; i <= n; i++)cin >> w[i];//for (int i = n; i >= 1; i--)//{//	f[i] = max(f[i+1], f[i + 2] + w[i]);//由底层求到根节点//}//cout << f[1] << endl;for (int i = 1; i <= n; i++){//f[i] = max(f[i - 1], f[i - 2] + w[i]);//因为i为1时数组会越界,所以我们同时让下标加2f[i+2] = max(f[i+1], f[i] + w[i]);//由根节点求到叶子结点}cout << f[n+2] << endl;}return 0;
}

可见两种形式的状态转移方程虽然不相同,但是两者的本质都是通过大问题像小问题递归进行的求解。

3.典例1

 

 题目并不难理解(看好了哈,这个不是那个有向左走次数与向右走次数的差不超过1的那个),他是想让我们找出来一条最长路径,结合我们的前面的讲解,我们不难给出下面的dfs代码:

#include <bits/stdc++.h>using namespace std;
const int maxn = 105;
int n;
int mp[maxn][maxn];//表示店铺的价值int dfs(int x, int y)
{if (x > n||y>n)return 0;elsereturn max(dfs(x+1,y),dfs(x+1,y+1)) + mp[x][y];
}
int main()
{cin >> n;for (int i = 1; i <= n; i++)for (int j = 1; j <= i; j++)cin >> mp[i][j];cout << dfs(1, 1) << endl;return 0;
}

看看数据量,1000行,dfs肯定会崩掉的,我们只能来优化,

记忆化搜索的方法我这里就不展开写了,毕竟模板在那挺好写的,我们直接来看重头戏动态规划

3.1动态规划法降低时间复杂度

我们先来画出递归树:

从以上来看,我们的递推方程也会有正推和逆推两种方式,这两种方式的不同之处在于:

对于正推(也就是从上往下推)

      我们现在已知的子问题是最上层的7这个点,因为它只有一个选择,我们需要每次为该层的子问题选择最优解,我们知道从上往下看,要求是选右下或者正下(在二维数组中是这样的,在该图中就是左下),那么相当于我们在二维数组中,我们向最大层靠近(向下层)的过程中,就要每次选择上层的正上方的数或者左上方的数,然后取他们的最大值即可,当我们取到最后一行时,因为我们是for循环遍历,所以每个数都会遍历到,也就造成了我们的第n行每一列都会有一个最大值,我们无法确定最后一行哪一列才是最大值,所以最后还需要求出最大的那个数

对于逆推

     逆推则是从第n行出发,我们每次寻找的是使我们当前这一层能取到最,我们的最终结果应该汇聚到最顶部的根节点上,所以我们应该把每层的结果放到上一层中去,逐层往上送至顶点处,所以我们对于每个点的选择应该还是遵从选择右下或者正下的,也就是说,我们应该使起点处为该节点所对应的值(比如最后一行的第一个节点对应的值应该为4),所以虽然是向上遍历,但是我们的选择还是来自下方的两个数,这样既保证了我们第n行的n个起点的值为节点值,也保证了我们选择最大值得目的。

这是代码:

#include <bits/stdc++.h>using namespace std;
const int maxn = 105;
int n;
int mp[maxn][maxn];//表示店铺的价值
int f[maxn][maxn];int main()
{cin >> n;for (int i = 1; i <= n; i++)for (int j = 1; j <= i; j++)cin >> mp[i][j];//正推for(int i=1;i<=n;i++)for (int j = 1; j <= i; j++){f[i][j] = max(f[i -1][j], f[i - 1][j - 1]) + mp[i][j];}//这里我们需要注意的是,我们一次所求出的f[i][j]只是相对的第n行其中一个位置的加和最大值,也就是说我们在这次循环结束后并不能马上求出最大值,我们的最大值在第n行中,但是我们不能确定在第几列,所以我们要排序寻找sort(f[n]+1, f[n] + n+1);cout << f[n] << endl;//逆推//for (int i = n; i >= 1; i--)//	for (int j = 1; j <= i; j++)//		f[i][j] = max(f[i + 1][j], f[i + 1][j + 1]) + mp[i][j];我们的终点只有一个,所以说递推的终点只有一个//cout << f[1][1] << endl;return 0;
}

间章规律小总结(不知对否,还请慎读)

       从上面的例子中我们不难的发现,动态规划本质上就是递归加递推的过程,一边递归一遍利用递推公式求解上层问题,其中递归的过程体现在for循环中,递推的过程体现在状态转移方程中,还记得我开头提过的动态规划在“归”的过程中出结果吗,准确的来说是在递推的过程中出结果,我们都知道“递”和“归”是两个相反的过程,同样的,递归和递推也是如此,细心地朋友可能会发现,在上面的两种正逆序的不同遍历过程中,实际上他们所对应的递推公式也是相反的,直白的说,for循环和状态转移方程是相反的,在我们上面的典例1中,for循环由上向下遍历,那么状态转移方程的每一个状态就和前一个状态有关,反之,如果是逆序遍历,相当于递归方向由下到上,那么递推就要与其相反才能有效的求出结果从而退出递归状态,因而每个点的状态由他的后一个状态求出,(如果我嘟囔错了,还请给位大佬帮忙指正~~多谢)。

By the  way:前面的f表示的二维数组其实可以直接优化成一维数组,我们只需要保留上一层的对应的状态即可(别试正推,因为不行~QAQ)

 但是这个要慎用,一般不推荐,搞不好正逆推会出错的,写这个只是为了知道一些大佬写题解会用一维数组就行了。

 

4.最后一站:让我们来到经典背包问题

输入样例:

4 5
1 2
2 4
3 4
4 5

 输出样例:

8

这个问题可能和前面的大盗阿福类似,还是在限制条件下求解最优解问题,我们老规矩,先来写经典的dfs版本:

#include <bits/stdc++.h>using namespace std;
const int maxn = 1005;
int N,V;
int w[maxn], v[maxn];
int dfs(int x, int surV)//surV表示当前背包的剩余体积,x表示当前正在考虑第x个物品
{if (x > N)return 0;if (v[x] > surV)//该物品超出当前背包剩余体积,装不下,被迫继续寻找下一个物品return dfs(x + 1, surV);else if(surV>=v[x]){//能装下,但是我们可以自由选择装与不装return max(dfs(x + 1, surV - v[x])+w[x], dfs(x + 1, surV));}
}
int main()
{cin >> N >> V;for (int i = 1; i <= N; i++)cin >> v[i] >> w[i];cout << dfs(1, V) << endl;//从第一个物品开始考虑return 0;
}

下面还是直接看动态规划版本:记忆化搜索就是个模板,不是太难理解,而且和dfs差距不大。

建议还是先理解前面正逆序方式的不同:

#include <bits/stdc++.h>using namespace std;
const int maxn = 105;
int N,V;
int dp[maxn][maxn];//第一个下标表示背包的当前选择的物品,第二个下标为当前背包剩余体积
int w[maxn], v[maxn];
int dfs(int x, int surV)
{if (x > N)return 0;if (v[x] > surV)//该物品超出当前背包剩余体积,装不下,被迫继续寻找下一个物品return dfs(x + 1, surV);else if(surV>=v[x]){//能装下,但是我们可以自由选择装与不装return max(dfs(x + 1, surV - v[x])+w[x], dfs(x + 1, surV));}
}
int main()
{cin >> N >> V;for (int i = 1; i <= N; i++)cin >> v[i] >> w[i];倒推//for (int i = N; i >= 1; i--)//{//	for (int j = 0; j <= V; j++)//	{//		if (j < v[i])//			dp[i][j] = dp[i + 1][j];//		else if(j>=v[i])//		    dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - v[i]] + w[i]);//看到没,和我说的规律一样//	}//}// cout<<dp[1][V]<<endl;//终点在第一个物品//正推for(int i=1;i<=N;i++)for (int j = 0; j <= V; j++){if (j < v[i])dp[i][j] = dp[i - 1][j];else if (j >= v[i])dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]);//看到没,和我说的规律一样}cout << dp[N][V] << endl;//终点在第N个物品return 0;
}

5.总结

       动态规划是一个上下限都极高的算法,想要学会并不容易,不知我这七千五百字能够让你们学到多少,动态规划算法的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其他的算法。选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间。

6.金句省身

       不要期待突如其来的惊喜,更不要期待命运会突然得到改变。没有一蹴而就的成功,好运不过是努力的伏笔而已。真正让我们成长的力量,就藏在那些日复一日看似平常的坚持里。所以,不要抱怨,你只管努力,该来的成功不会远。

                                                                                                          ----------   摘自《人民日报》

 

相关文章:

动态规划入门

前言&#xff1a;首先&#xff0c;什么是动态规划&#xff1f; 动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中&#xff0c;可能会有许多可行解。每一个解都对应于一个值&#xff0c;我们希望找到具有最优值的解。动态规划算法与分治法类似&#xff0c;其基本思…...

day26 SpringBootWeb案例(二)

目录 SpringBootWeb案例 1. 新增员工 1.1 需求 1.2 开发 1.3 测试 2. 文件上传 2.1 简介 2.2 本地存储 2.3 阿里云OSS 3. 配置文件 3.1 Value 3.2 yml配置 3.3 ConfigurationProperties 4. 修改员工 4.1 需求 4.2 查询回显 4.3 保存修改 SpringBootWeb案例 前…...

力扣-《剑指offer》-哈希表-刷题笔记

目录 第一题&#xff1a;03.数组中重复的数字 第二题&#xff1a;39.数组中出现次数超过一半的数字 第三题&#xff1a;50.第一个只出现一次的字符 第四题&#xff1a;53. &#xff08;0-n-1&#xff09;中缺失的数字 第一题&#xff1a;03.数组中重复的数字 我的答案&…...

【SpringBoot】| 邮箱发送验证码,你会了吗?

目录&#x1f981; 题外话&#x1f981; 提前准备2.1 配置邮箱第三方登录2.1.1 点击设置——账户2.1.2 开启POP3/SMTP服务2.2 添加依赖2.3 yaml配置&#x1f981; 进入主题&#x1f981; 测试使用&#x1f981; 尾声3.1 安利一个生成验证码的工具类3.1.1 添加依赖3.1.2 编写配置…...

Linux系统安装部署及配置Grafana

TOC 用于 UI 展示 wget https://dl.grafana.com/oss/release/grafana-8.0.3-1.x86_64.rpm1 安装 grafana 1.1 下载安装 wget https://dl.grafana.com/oss/release/grafana-8.0.3-1.x86_64.rpmsudo yum install grafana-8.0.3-1.x86_64.rpm1.2 启动&状态查看 sudo syst…...

Python3 入门教程||Python3 输入和输出||Python3 File 方法

Python3 输入和输出 在前面几个章节中&#xff0c;我们其实已经接触了 Python 的输入输出的功能。本章节我们将具体介绍 Python 的输入输出。 输出格式美化 Python 两种输出值的方式: 表达式语句和 print() 函数。(第三种方式是使用文件对象的 write() 方法; 标准输出文件可以…...

有效的字母异位词(力扣刷题)

给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true 示例 2: 输入: s "rat", t "car" 输出: false 说明: 你可以假设字符串只包含小写字母。 …...

73、介绍下 HashMap 的底层数据结构

73、介绍下 HashMap 的底层数据结构 我们现在用的都是 JDK 1.8&#xff0c;底层是由“数组链表红黑树”组成&#xff0c;如下图&#xff0c;而在 JDK 1.8 之前是由“数组链表”组成。 1.Hash Hash叫做”散列表“&#xff0c;就是把任意长度的输入&#xff0c;通过散列算法&am…...

系统集成路由器OSPF动态、综合路由配置

实验任务&#xff1a;动态路由协议RIP、OSPF协议的内容和特点动态路由RIP、OSPF实验&#xff0c;建立拓扑pc1>>R1>>R2>>R3>>pc2&#xff0c;使pc1与pc2能相互通信&#xff0c;并配置PC端静默接口。熟悉配置vlan间路由技术&#xff1a;多层交换机虚拟接…...

【力扣周赛 338】

6354. K 件物品的最大和 - 力扣&#xff08;Leetcode&#xff09;袋子中装有一些物品&#xff0c;每个物品上都标记着数字 1、0或 -1。给你四个非负整数 numOnes、numZeros、numNegOnes和 k。袋子最初包含&#xff1a;numOnes 件标记为 1 的物品。numZeroes 件标记为 0 的物品。…...

大数据Flink进阶(八):Apache Flink架构介绍

Apache Flink架构介绍 一、Flink组件栈 在Flink的整个软件架构体系中,同样遵循这分层的架构设计理念,在降低系统耦合度的同时,也为上层用户构建Flink应用提供了丰富且友好的接口。...

Mars3d项目启动上的一些坑

前言 最近新入职了一家公司&#xff0c;公司新开了有个未来城市的项目&#xff0c;需要用到3D城市建模&#xff0c;公司老总选了Mars3d作为前端框架&#xff0c;项目分给我了&#xff0c;又是一个全新的领域&#xff0c;开搞吧&#xff01; 下面是自己遇到的几个小问题&#x…...

通俗易懂【Springboot】 单文件下载和批量下载(多个文件合成一个压缩包下载)

文章目录一.单文件下载1.简单理解文件下载2.单文件下载的具体代码实现3.测试4.单文件下载整体代码二.多文件批量下载&#xff08;多个文件合成一个压缩包下载&#xff09;1.多文件下载的实现方式&#xff0c;这里使用了ZipOutputStream2.具体代码实现3.测试4.文件批量下载&…...

CnOpenData中国行政区划shp数据

一、数据简介 中国行政区划数据是重要的基础地理信息数据&#xff0c;目前不同来源的全国行政区划数据非常多&#xff0c;但能够开放获取的高质量行政区域数据少之又少。基于此&#xff0c;锐多宝的地理空间制作一套2013-2023年可开放获取的高质量行政区划数据。该套数据以2022…...

GPT-4零失误通关大厂模拟面试,offer拿到手软?与AGI首次接触

来源: FoxyearMeta “GPT-4可被视作AGI &#xff08;通用人工智能&#xff09;的早期版本。” 如若从他人口中说出&#xff0c;或许是无稽之谈—— 但是由微软雷蒙德研究院机器学习理论组负责人万引大神Sbastien Bubeck与2023新视野数学奖得主Ronen Eldan、2023新晋斯隆研究奖得…...

Hardhat 环境搭建及教程示例

一.安装node.js curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash nvm install 18 nvm use 18 nvm alias default 18 npm install npm --global # Upgrade npm to the latest version 二. 安装hardhat 2.1 创建hardhat安装目录 mkdir hard…...

复杂链表的复制-剑指Offer35-java

一、题目描述 请实现 copyRandomList 函数&#xff0c;复制一个复杂链表。在复杂链表中&#xff0c;每个节点除了有一个 next 指针指向下一个节点&#xff0c;还有一个 random 指针指向链表中的任意节点或者 null。 示例 1&#xff1a; 输入&#xff1a;head [[7,null],[13,…...

【Linux】进程理解与学习Ⅰ-进程概念

环境&#xff1a;centos7.6&#xff0c;腾讯云服务器Linux文章都放在了专栏&#xff1a;【Linux】欢迎支持订阅&#x1f339;相关文章推荐&#xff1a;【Linux】冯.诺依曼体系结构与操作系统进程概念什么是进程&#xff1f;进程是什么&#xff1f;我们打开任务管理器可以看到有…...

WebKitX ActiveX 6.0 X86 Crack

WebKitX ActiveX将 Chromium Embedded Framework (CEF3) 包装到一个进程外的 ActiveX 组件中&#xff0c;以便与 OLE/COM 语言一起使用。Chromium Embedded Framework 封装了 WebKit Blink HTML5 Renderer 和 Google V8 JavaScript Engine。这是一个用于商业用途的生产级稳定组…...

开源项目:数据库表结构生成文档工具

目录 一、软件介绍 二、技术框架 三、功能介绍 四、代码展示 1、获取数据库信息部分代码 2、导出Html文档代码 五、运行效果 六、项目开源地址 一、软件介绍 今天给大家分享我自己编写的数据库表结构文档生成工具&#xff0c;方便大家在实际开发当中&#xff0c;可以很方便导出…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...