ET算法【动态规划】

线性dp:dp[i][j] 由 dp[i - 1][j] 通过加减乘除等线性运算得到

状压dp:dp[i][j] 表示一个用二进制数表示的子集来反映当前状态,如7 =(111)(选了三个)

期望dp:dp[i][j] 表示期望或者概率

存在性dp:dp[i][j] 表示目标状态是否存在

树形dp:通过树状结构来状态转移,通常用到DFS

数位dp:[1,n]之中包含多少个69

一、线性DP

1.最长上升子序列

(1)基础版

P1105 - 最长上升子序列(easy) - ETOJ (eriktse.com)

找到一个数组中一直增大的最长子序列(可以不连续),对于每一个点,要么作为起点,要么在左边找一个点连接,因此可以用线性dp,dp[ i ]表示到i点时的最大子序列长度。

复杂度为O(n^{2})

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;const int N = 1e3 + 10;
ll a[N], dp[N];int main() {int n; cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];for(int i = 1; i <= n; i++){dp[i] = 1;for(int j = 1; j < i; j++){if(a[i] >= a[j]) dp[i] = max(dp[i], dp[j] + 1);}}cout << *max_element(dp + 1, dp + 1 + n) << '\n';
}

(2)贪心 + 二分优化

用一个Array数组记录当前的最长上升子序列,长度为len,从头到尾遍历a[i]数组

①若a[i]  >  Array[len],Array[++len] = a[i]

②若a[i] <= Array[len],此时把Array中第一个大于a[i]的元素替换为a[i],这样保证的是子序列中的元素尽可能的小,则后面进入的元素尽可能的多

    int n; cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];int len = 0;//记录当前最长上升序列的长度for(int i = 1; i <= n; i++){//返回第一个大于等于a[i]的下标int cnt = lower_bound(ans + 1, ans + len + 1, a[i]) - ans;ans[cnt] = a[i];//如果此时cnt大于len就直接更新lenlen = max(cnt, len);	}cout << len << endl;

2.最长公共子序列

给定字符串a,b,求最长公共子序列,a有n个字符,b有m个字符,则答案为dp[n][m]

复杂度为O(nm)

转移方程:

① 若a[i] == b[j]  dp[i][j] = dp[i - 1][j - 1] + 1

② 若a[i] !=  b[j]  dp[i][j] = max(dp[i][j - 1], dp[i - 1][j])

3.Problem - 467C - Codeforces

思维题

#include<bits/stdc++.h>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;const int N = 5e3 + 10;
ll a[N], pre[N], dp[N][N];void solve() {int n, m, k; cin >> n >> m >> k;for(int i = 1; i <= n; i++) cin >> a[i];for(int i = 1; i <= n; i++) pre[i] = pre[i - 1] + a[i];dp[1][1] = a[1];for(int i = m; i <= n; i++){for(int j = 1; j <= k; j++){dp[i][j] = max(dp[i - 1][j], dp[i - m][j - 1] + pre[i] - pre[i - m]);}}cout << dp[n][k] << '\n';
}signed main() {qioint T = 1;
//	cin >> T;while (T--)	solve();
}

4.Problem - 788A - Codeforces

思维题,dp[i][0]存正贡献,dp[i][1]存负贡献

#include<bits/stdc++.h>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;
#define int ll
const int N = 1e5 + 10;
int a[N], d[N], dp[N][2];void solve() {int n; cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];for(int i = 1; i <= n - 1; i++) d[i] = abs(a[i + 1] - a[i]);
//	for(int i = 1; i <= n; i++) cout << d[i] << ' ';for(int i = 1; i <= n - 1; i++){dp[i][0] = max(dp[i - 1][1] + d[i], d[i]);dp[i][1] = max(dp[i - 1][0] - d[i], 0ll);}int ans = 0;for(int i = 1; i <= n - 1; i ++){ans = max(ans, max(dp[i][0], dp[i][1]));}cout << ans ;
}signed main() {qioint T = 1;
//	cin >> T;while (T--)	solve();
}

二、状压DP

一般用一个01字符串来表示各个点的状态,就是将一种情况压缩为一个数字或者字符来表示这种情况,这些数字或者字符形成的字符串即为总体情况的状态

1.最短Hamilton路径

P10447 最短 Hamilton 路径 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
using namespace std;const int N = 1e5 + 10;
int dp[1 << 20][21];
int dist[21][21];int main() {memset(dp, 0x3f, sizeof dp);int n; cin >> n;for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){cin >> dist[i][j];}}//开始:集合中只有点0,起点和终点都是0dp[1][0] = 0;//从小集合扩展到大集合,集合用S的二进制表示for(int S = 1; S < (1 << n); S++){//枚举点jfor(int j = 0; j < n; j++){//如果S中有j这个点if((S >> j) & 1){//枚举到达j的点kfor(int k = 0; k < n; k++){//S ^ (1 << j):S中去掉j点,  >> k & 1 去掉j点后S中所有为1的点if((S ^ (1 << j)) >> k & 1){dp[S][j] = min(dp[S][j], dp[S ^ (1 << j)][k] + dist[k][j]);}}}}}//dp[(1 << n) - 1][n - 1]即为包含所有的点,终点为n - 1的最短路径cout << dp[(1 << n) - 1][n - 1] << '\n';
}

三、区间DP

区间DP中dp[i][j]表示的即为区间i - j内种合法的个数,数据范围通常较小,转移方程一般为:

① dp[i][j] = dp[i + 1][j]

② dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]),  i <= k < j

经典问题为取石子问题。

初始化一般为for(int i = 1; i <= n; i++) dp[i][i] = 0;

1.Problem - 2476 (hdu.edu.cn)

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;const int N = 1e2 + 10;
const int inf = 0x3f3f3f3f;
int dp[N][N];void solve() {string a, b;while(cin >> a >> b){if(a == "11") break;int n = a.length();a = ' ' + a, b = ' ' + b;for(int i = 1; i <= n; i++) dp[i][i] = 1;for(int len = 2; len <= n; len++){for(int i = 1; i <= n - len + 1; i++){int j = i + len - 1;dp[i][j] = inf;if(b[i] == b[j]){dp[i][j] = dp[i + 1][j];}else{for(int k = i; k < j; k++){dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);}}}}for(int j = 1; j <= n; j++){if(a[j] == b[j]){dp[1][j] = dp[1][j - 1];}else{for(int k = 1; k < j; k++){dp[1][j] = min(dp[1][j], dp[1][k] + dp[k + 1][j]);}}}cout << dp[1][n] << '\n';;}
}signed main() {qioint T = 1;
//	cin >> T;while (T--)	solve();
}

2.2955 -- Brackets (poj.org)

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;const int N = 1e2 + 10;
const int inf = 0x3f3f3f3f;
int dp[N][N];
string s;bool isok(int i, int j){if(s[i] == '[' && s[j] == ']') return true;if(s[i] == '(' && s[j] == ')') return true;return false;	
}void solve() {	while(cin >> s){if(s == "end") break;int n = s.length();	s = ' ' + s;//		cout << "len:" << n <<'\n';memset(dp, 0, sizeof dp);for(int len = 2; len <= n; len++){for(int i = 1; i <= n - len + 1; i++){int j = i + len - 1;if(isok(i, j)){dp[i][j] = dp[i + 1][j - 1] + 2;}for(int k = i; k < j; k++){dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]);}}}cout << dp[1][n] << '\n';}
}signed main() {qioint T = 1;
//	cin >> T;while (T--)	solve();
}

四、数位DP

原理没有太懂,这里记一下板子

P2602 [ZJOI2010] 数字计数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

1.递推实现

#include<bits/stdc++.h>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0),cout.tie(0);
typedef long long ll;
typedef double db;const int N = 15;
ll ten[N], dp[N];
ll cnta[N], cntb[N]; //cnt[i]统计数字i出现了多少次
ll num[N];void init(){ten[0] = 1;for(int i = 1; i <= N; i++){//ten[i]:10的i次方dp[i] = dp[i - 1] * 10 + ten[i - 1]; ten[i] = 10 * ten[i - 1];}
}void solve(ll x, ll* cnt){//分解数字xint len = 0;while(x){num[++len] = x % 10;x /= 10;}//从高到低处理x的每一位for(int i = len; i >= 1; i--){for(int j = 0; j <= 9; j++){cnt[j] += dp[i - 1] * num[i];}//特判最高位比num[i]小的数字for(int j = 0; j < num[i]; j++){cnt[j] += ten[i - 1];}//特判最高位的数字num[i]ll num2 = 0;for(int j = i - 1; j >= 1; j--){num2 = num2 * 10 + num[j];}cnt[num[i]] += num2 + 1;cnt[0] -= ten[i - 1];}	
}signed main() {init();ll a, b; cin >> a >> b;solve(a - 1, cnta);solve(b, cntb);for(int i = 0; i <= 9; i++) cout << cntb[i] - cnta[i] << " ";
}

2.记忆化搜索实现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;const int N = 15;
ll dp[N][N];
int num[N], now; //now:当前统计0-9的哪一个数字//pos:当前处理到第pos位
ll dfs(int pos, int sum, bool lead, bool limit){ll ans = 0;//递归到第0位就返回结果if(pos == 0) return sum;//记忆化搜索if(!lead && !limit && dp[pos][sum] != -1) return dp[pos][sum];//这一位的最大值,如324的第3位是up = 3int up = (limit ? num[pos] : 9);for(int i = 0; i <= up; i++){//计算000-099if(i == 0 && lead) ans += dfs(pos - 1, sum, true, limit && i == up);//计算200-299else if(i == now) ans += dfs(pos - 1, sum + 1, false, limit && i == up);//计算100-199else if(i != now) ans += dfs(pos - 1, sum, false, limit && i == up);}//状态记录:有前导0,无数位限制if(!lead && !limit) dp[pos][sum] = ans;return ans;
}ll solve(ll x) {int len = 0;while(x){num[++len] = x % 10;x /= 10;}memset(dp, -1, sizeof dp);return dfs(len, 0, true, true);
}signed main() {ll a, b; cin >> a >> b;for(int i = 0; i < 10; i++) now = i, cout << solve(b) - solve(a - 1) << " ";return 0;
}

五、树形DP

即在树上用DP来维护最值,因为树上的子树天然满足dp的递归性质,一般用dp[i][j],i表示节点,j表示题目要求的条件,使用dfs进行递推转移

1.Problem - 1926G - Codeforces

因为C的状态不确定而又对其他的点有影响,所以需要维护三个状态的dp

#include<bits/stdc++.h>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;const int N = 2e5 + 10;
vector<int> g[N];
ll dp[N][3]; //dp[][0]都没有,dp[][1]在睡觉,dp[][2]在嗨
char s[N];void dfs(int now){dp[now][0] = dp[now][1] = dp[now][2] = 0;for(auto nex : g[now]){dfs(nex);if(s[nex] == 'S'){dp[now][1] += dp[nex][1];dp[now][2] += dp[nex][1] + 1;dp[now][0] = 1e9;}if(s[nex] == 'P'){dp[now][1] += dp[nex][2] + 1;dp[now][2] += dp[nex][2];dp[now][0] = 1e9;}if(s[nex] == 'C'){dp[now][1] += min(dp[nex][1], dp[nex][2] + 1);dp[now][2] += min(dp[nex][1] + 1, dp[nex][2]);dp[now][0] = max(dp[now][0], dp[nex][0]);}}if(s[now] == 'S') dp[now][0] = dp[now][2] = 1e9;if(s[now] == 'P') dp[now][0] = dp[now][1] = 1e9;
}void solve() {int n; cin >> n;for(int i = 1; i <= n; i++) g[i].clear();for(int i = 2; i <= n; i++){int x; cin >> x;g[x].push_back(i);}for(int i = 1; i <= n; i++) cin >> s[i];dfs(1);cout << min(dp[1][0], min(dp[1][1], dp[1][2])) << '\n';
}signed main() {qioint T = 1;cin >> T;while (T--)	solve();
}

2.Problem - 1561 (hdu.edu.cn)

类似区间DP,枚举每颗子树now上分别分有j : 0 ~ m条边的情况,再枚举now子树nex上分别有k : 0 ~ j - 1条边的情况

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;const int N = 2e2 + 10;
int n, m;
struct node{int v;ll w;
};
vector<node> g[N];
ll dp[N][N];//第i个节点,选了j条边时的最大值
int sum[N];//以i为根节点的子树中边的个数
void dfs(int now){for(int i = 0; i < g[now].size(); i++){int nex = g[now][i].v, w = g[now][i].w;dfs(nex);sum[now] += sum[nex] + 1;for(int j = min(m, sum[now]); j >= 0; j--){for(int k = 0; k <= min(sum[nex], j - 1); k++){dp[now][j] = max(dp[now][j], dp[now][j - k - 1] + dp[nex][k] + w);}}}
}void solve() {while(cin >> n >> m){if(n == 0 && m == 0) break;memset(dp, 0, sizeof dp);memset(sum, 0, sizeof sum);for(int i = 0; i <= n; i++) g[i].clear();for(int i = 1; i <= n; i++){int u; cin >> u;ll w; cin >> w;g[u].push_back({i, w});}dfs(0);cout << dp[0][m] << '\n';}}signed main() {qioint T = 1;
//	cin >> T;while (T--)	solve();
}

六、存在性DP

比较简单

1.Problem - 1472B - Codeforces

#include<bits/stdc++.h>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;const int N = 1e3 + 10;
int a[N], dp[N];void solve() {memset(dp, 0, sizeof dp);int n; cin >> n;int sum = 0;for(int i = 1; i <= n; i ++){cin >> a[i];sum += a[i];}if(sum % 2 == 1){cout << "NO\n";return;}dp[0] = 1;for(int i = 1; i <= n; i++){for(int j = sum / 2; j >= a[i]; j--){dp[j] |= dp[j - a[i]];}}if(dp[sum / 2]) cout << "YES\n";else cout << "NO\n";
}signed main() {qioint T = 1;cin >> T;while (T--)	solve();
}

七、记忆化搜索

在DFS回溯的过程中,更新从当前格子出发能够得到的最大价值,以避免重复的计算。
因为回溯时,上一个格子的所有可能情况都已经考虑过了,也就是说上一个格子的状态已经是最优的了,所以直接用上一个格子的值来更新当前格子。在当前格子的所有方向都回溯完时,当前格子也就达到了最优值,继续更新之后的。

1.Problem - 1078 (hdu.edu.cn)

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
typedef long long ll;
typedef double db;const int N = 1e2 + 10;
int mp[N][N], dp[N][N];
int n, k;
int xx[10] = {1, 0, -1, 0}, yy[10] = {0, 1, 0, -1};
bool isok(int x, int y){if(1 <= x && x <= n && 1 <= y && y <= n) return true;else return false;
}
int dfs(int nowx, int nowy){int res = 0;if(!dp[nowx][nowy]){for(int i = 0; i < 4; i++){for(int j = 1; j <= k; j++){int nexx = nowx + xx[i] * j, nexy = nowy + yy[i] * j;if(isok(nexx, nexy) && mp[nexx][nexy] > mp[nowx][nowy]){res = max(res, dfs(nexx, nexy));} }}dp[nowx][nowy] = res + mp[nowx][nowy];}return dp[nowx][nowy];
}void solve() {	while(cin >> n >> k){if(n == -1 && k == -1) break;memset(dp, 0, sizeof dp);for(int i = 1; i <= n; i++){for(int j = 1; j <= n; j++){cin >> mp[i][j];}}cout << dfs(1, 1) << '\n';}
}signed main() {qioint T = 1;
//	cin >> T;while (T--)	solve();
}

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

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

相关文章

yolo8 目标检测、鉴黄

省流 看前必读 别浪费时间 &#xff1a;本文只是一个记录&#xff0c;防止自己下次被改需求时浪费时间&#xff0c;在这里就随意的写了一下文章记录整个步骤&#xff0c;但是文章想必肯定没有对应的教程讲的详细&#xff0c;该文章只适合想要快速按照步骤完成一个简单的 demo 的…

学习之git

github 创建远程仓库 代码推送 Push 代码拉取 Pull 代码克隆 Clone SSH免密登录 Idea集成GitHubGitee码云 码云创建远程仓库 Idea集成Gitee码云 码云连接Github进行代码的复制和迁移GitLab gitlab服务器的搭建和部署 Idea集成GitLabgit概述 一切皆本地 版本控制工具 集中…

win10配置adb环境变量

初始状态&#xff1a; 最简单的配置方案&#xff0c;直接复制adb所在路径&#xff1a; 粘贴进来确定即可&#xff1a; 然后打开 cmd 查看已经配置成功了&#xff1a;

【c++】cout打印char * 或者char[]的细节详解

目录 char* 类型 1.打印指向的字符串 2.打印指针指向的地址 问题描述 解决方法 char型数组 1. 想要输出字符串 2. 想输出字符数组的地址 printf 和cout 的对比 1.打印首字符 2.打印字符串 3.打印字符串首地址 &#x1f497;感谢阅读&#xff01;&#x1f497; char*…

用powermock编写单元测试

1、pom文件引入jar包 <!-- 单元测试 start --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope> </dependency> <dependency>&…

基于ZYNQ SOC的软件无线电处理平台

板载SOC实时处理器&#xff1a;XC7Z020-2CLG484I板载2片AD9361射频收发芯片&#xff0c;兼容AD80305具有1路千兆以太网口具有1个USB串口、1个USB OTG、1个SD卡ADC/DAC采集位宽&#xff1a;12位2路TX、2路RX&#xff0c;可实现全双工或者半双工 基于Xilinx ZYNQ SOC的软件无线电…

第 4 章 第 4 章 卷积神经网络-datawhale ai夏令营

独热向量 y ′ 的长度决 定了模型可以识别出多少不同种类的东西。我们希望 y ′ 和 yˆ 的交叉熵越小越好。 为了避免过拟合&#xff0c;在做图像识别的时候&#xff0c;考虑到图像本身的特性&#xff0c;并不一定 需要全连接&#xff0c;即不需要每个神经元跟输入的每个维度都…

Python中排序算法之插入排序

1 插入排序算法原理 插入排序算法与《Python中排序算法之选择排序》中提到的选择排序算法类似&#xff0c;也是将要排序的数列分为两个子数列&#xff08;红色框数列和绿色框数列&#xff09;&#xff0c;不同之处在于插入排序算法从绿色框子数列中逐个选择数字&#xff0c;之…

单片机内存区域划分

目录 一、C 语言内存分区1、栈区2、堆区3、全局区&#xff08;静态区&#xff09;4、常量区5、代码区6、总结 二、单片机存储分配1、存储器1.1 RAM1.2 ROM1.3 Flash Memory1.4 不同数据的存放位置 2、程序占用内存大小 一、C 语言内存分区 C 语言在内存中一共分为如下几个区域…

【生日视频制作】农村大马路绿色墙体广告标语喷漆AE模板修改文字软件生成器教程特效素材【AE模板】

生日视频制作教程农村大马路墙体广告标语喷漆AE模板改文字素材 怎么如何做的【生日视频制作】农村大马路绿色墙体广告标语喷漆AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件 下载AE模板 把AE模板导入AE软件 修改图片或文字 渲染出…

【最新消息】211高校,拟撤销测绘工程专业

近日&#xff0c;中国石油大学&#xff08;北京&#xff09;教务处发布《关于公示2024年度拟撤销本科专业的通知》&#xff0c;拟撤销音乐学、建筑学、测绘工程等9个本科专业。 通知内容如下&#xff1a; 根据《教育部高等教育司关于开展2024年度普通高等学校本科专业设置工作的…

【STM32】IIC

超级常见的外设通信方式&#xff0c;一般叫做I方C。 大部分图片来源&#xff1a;正点原子HAL库课程 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 基本概念 1.1 总线结构 1.2 IIC协议 1.3 软件模拟IIC逻辑 2 AT24C02 2.1 设备地址与…

一次VUE3 使用axios调用萤石云OpenAPI踩坑经历

通过调用萤石云的获取设备列表功能&#xff0c;我们可以根据 ACCESS_TOKEN 获取该用户下的设备列表。 Python 调用接口 根据接口文档[1]&#xff0c;使用Python&#xff0c;很轻松就能获取到该列表&#xff0c;代码如下&#xff08;该代码用于拼接生成vue代码&#xff0c;这是…

Codeforces Round 969 (Div. 2) 题ABC详细题解,包含(C++,Python语言描述)

前言&#xff1a; 首先让我们恭喜tourist创造历史 他是第一&#xff0c;他又是第一&#xff0c;他总是第一&#xff0c;第一个codefores上4000分的&#xff0c;创造一个新的段位:Tourist&#xff0c;他的名字就是一个新的段位&#xff0c;他就是最高的山&#xff0c;最长的河 本…

访问win10共享文件夹:用户或密码不正确 以及 未授予用户在此计算机上的请求登录类型

因为安装的是神州网信政府版&#xff0c;该版本通常包含更严格的安全策略和访问控制&#xff0c;设置了共享文件夹后&#xff0c;访问共享文件夹时出现错误。 1、首先报错&#xff1a;用户或密码不正确 将》网络访问&#xff1a;本地账户的共享和安全模型&#xff0c;修改为&a…

开源通用验证码识别OCR —— DdddOcr 源码赏析(二)

文章目录 前言DdddOcr分类识别调用识别功能classification 函数源码classification 函数源码解读1. 分类功能不支持目标检测2. 转换为Image对象3. 根据模型配置调整图片尺寸和色彩模式4. 图像数据转换为浮点数据并归一化5. 图像数据预处理6. 运行模型&#xff0c;返回预测结果 …

Python测试之测试覆盖率统计

本篇承接上一篇 Python测试框架之—— pytest介绍与示例&#xff0c;在此基础上介绍如何基于pytest进行测试的覆盖率统计。 要在使用 pytest 进行测试时检测代码覆盖率&#xff0c;可以使用 pytest-cov 插件。这个插件是基于 coverage.py&#xff0c;它能帮助你了解哪些代码部…

人工智能和机器学习5 (复旦大学计算机科学与技术实践工作站)语言模型相关的技术和应用、通过OpenAI库,调用千问大模型,并进行反复询问等功能加强

前言 在这个日新月异的AI时代&#xff0c;自然语言处理&#xff08;NLP&#xff09;技术正以前所未有的速度改变着我们的生活方式和工作模式。作为这一领域的佼佼者&#xff0c;OpenAI不仅以其强大的GPT系列模型引领风骚&#xff0c;还通过其开放的API接口&#xff0c;让全球开…

哈工大-操作系统L30

文件使用磁盘的实现 fd文件描述符 buf内存缓冲区 count读写字符的个数 file->inode获得inode file_write写文件 inode映射表 读写的内存缓冲区buf,file字符流的位置200-212,根据inode提供的索引号找到块号,根据buf形成请求队列&#xff0c;再放入电梯队列 fseek调整读…

Jenkins安装使用详解,jenkins实现企业级CICD流程

文章目录 一、资料1、官方文档 二、环境准备1、安装jdk172、安装maven3、安装git4、安装gitlab5、准备我们的springboot项目6、安装jenkins7、安装docker8、安装k8s&#xff08;可选&#xff0c;部署节点&#xff09;9、安装Harbor10、准备带有jdk环境的基础镜像 三、jenkins实…