From a926d878d1978445e2b1f8ce671a3059a317c72c Mon Sep 17 00:00:00 2001 From: Zengtudor Date: Thu, 19 Sep 2024 11:11:59 +0800 Subject: [PATCH] change to utf8 --- 20240919/CSP常考算法模板/BFS.cpp | 14 +++++----- 20240919/CSP常考算法模板/DFS.cpp | 26 +++++++++---------- 20240919/CSP常考算法模板/LCA_倍增.cpp | 18 ++++++------- .../P3379【模板】LCA_倍增 -邻接表.cpp | 12 ++++----- .../P3379【模板】LCA_倍增 -邻接表_todo.cpp | 12 ++++----- 20240919/CSP常考算法模板/RMQ.cpp | 8 +++--- 20240919/CSP常考算法模板/全排列.cpp | 2 +- .../区间dp/区间dp_合并石子.cpp | 16 ++++++------ 20240919/CSP常考算法模板/快速幂.cpp | 6 ++--- .../最小生成树/最小生成树_Prim(稠密图)..cpp | 2 +- .../最小生成树/最小生成树_kruskal(稀疏图).cpp | 6 ++--- .../最短路径/单源最短路径Dijkstra.cpp | 8 +++--- .../最短路径/单源最短路径SPFA(有负边).cpp | 4 +-- .../最短路径/多源最短路径Floyed.cpp | 8 +++--- 20240919/CSP常考算法模板/树上问题_dfs.cpp | 12 ++++----- .../线性dp_求最长不下降序列_逆推.cpp | 10 +++---- .../线段树(区间修改,区间查询).cpp | 20 +++++++------- 20240919/CSP常考算法模板/背包问题_01.cpp | 10 +++---- 20240919/CSP常考算法模板/背包问题_多重.cpp | 8 +++--- 20240919/CSP常考算法模板/背包问题_完全.cpp | 6 ++--- 20 files changed, 104 insertions(+), 104 deletions(-) diff --git a/20240919/CSP常考算法模板/BFS.cpp b/20240919/CSP常考算法模板/BFS.cpp index 83620aa..d3ab6f7 100644 --- a/20240919/CSP常考算法模板/BFS.cpp +++ b/20240919/CSP常考算法模板/BFS.cpp @@ -7,30 +7,30 @@ struct node { queue q; int a[51][51]; -int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; // +int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; // 方向数组 bool flag = false, book[51][51]; int n, m, sx, sy, ex, ey; void bfs(int sx,int sy) { - q.push({sx, sy, 0}); // ֮, ԭ + q.push({sx, sy, 0}); // 星星之火, 可以燎原 book[sx][sy] = true; while(!q.empty() && !flag) { node temp = q.front(); q.pop(); for(int i=0; i<4;i++) { - //µλ + //算出新的位置坐标 int nx = temp.x + dir[i][0]; int ny = temp.y + dir[i][1]; - //жµλǷԽ + //判断新的位置是否越界 if(nx<1 || nx > n || ny < 1 || ny > m) continue; - // µλƽ û߹ + // 如果新的位置是平地 并且 没有走过 if(a[nx][ny]==0 && !book[nx][ny]) { q.push({nx, ny, temp.s+1}); book[nx][ny] = true; - // µλǷΪյ + // 新的位置是否为终点 if(nx==ex && ny==ey) { flag = true; cout<=minn) // δյ㲽Ѿﵽ򳬹Сֵͷء + // 剪枝 + if(step>=minn) // 如果未到终点步数就已经达到或超过最小值,就返回。 return; - // öÿһ + // 枚举每一个方向 for(int i=0; i<=3; i++){ - //һ + //计算下一个点的坐标 int nx=x+dir[i][0]; int ny=y+dir[i][1]; - // жǷԽ + // 判断是否越界 if(nx<1 || nx>n || ny<1 || ny>m) continue; if(a[nx][ny]==0 && !book[nx][ny]){ book[nx][ny]=true; dfs(nx,ny,step+1); - book[nx][ny]=false; // + book[nx][ny]=false; // 回溯 } } @@ -46,7 +46,7 @@ int main(){ int i ,j,startx,starty; cin>>n>>m; - //Թ + //读入迷宫 for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>a[i][j]; diff --git a/20240919/CSP常考算法模板/LCA_倍增.cpp b/20240919/CSP常考算法模板/LCA_倍增.cpp index fd88b36..984f8e3 100644 --- a/20240919/CSP常考算法模板/LCA_倍增.cpp +++ b/20240919/CSP常考算法模板/LCA_倍增.cpp @@ -10,7 +10,7 @@ struct Edge { int n,m,s; int depth[N], Log[N]; -int dbl[N][20]; // +int dbl[N][20]; //倍增数组 int head[N], tot; void addEdge(int x,int y) { @@ -24,18 +24,18 @@ void dfs(int cur, int fa) { dbl[cur][0]=fa; for(int i=1; (1<0; i=e[i].nxt) { - if(e[i].to != fa) // ӽڵ + if(e[i].to != fa) // 遍历子节点 dfs(e[i].to, cur); } } int lca(int x,int y) { - // ͬһ߶ȣһ - if(depth[x]=0; i--) if(dbl[x][i] != dbl[y][i]) { x=dbl[x][i]; @@ -57,7 +57,7 @@ int lca(int x,int y) { } /* -㷨ʱ临ӶO(nlogn) +倍增算法时间复杂度是O(nlogn) */ int main() { scanf("%d%d%d",&n,&m,&s); @@ -67,9 +67,9 @@ int main() { addEdge(x,y); addEdge(y,x); } - dfs(s,0); // + dfs(s,0); // 建树 - // ԤŻ + // 预处理,常数优化 for(int i=2; i<=n; i++) { Log[i]=Log[i>>1] + 1; } diff --git a/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表.cpp b/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表.cpp index 049d98a..1618250 100644 --- a/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表.cpp +++ b/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表.cpp @@ -5,7 +5,7 @@ const int N = 500001; int n,m,s; int depth[N], Log[N]; -int dbl[N][20]; // +int dbl[N][20]; //倍增数组 int tot; vector graph[N]; @@ -28,7 +28,7 @@ void dfs(int cur, int fa) { } int lca(int x,int y) { - // ͬһ߶ȣһ + // 把两个点升至同一高度,再一起跳 // TODO if(depth[x]=0;i--) @@ -58,7 +58,7 @@ int lca(int x,int y) { } /* -㷨ʱ临ӶO(nlogn) +倍增算法时间复杂度是O(nlogn) */ int main() { scanf("%d%d%d",&n,&m,&s); @@ -69,9 +69,9 @@ int main() { graph[x].push_back(y); graph[y].push_back(x); } - dfs(s,0); // + dfs(s,0); // 建树 - // ԤŻ + // 预处理,常数优化 for(int i=2; i<=n; i++) { //todo Log[i]=Log[i/2]+1; diff --git a/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表_todo.cpp b/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表_todo.cpp index 3bb9c75..7c7bd14 100644 --- a/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表_todo.cpp +++ b/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表_todo.cpp @@ -5,7 +5,7 @@ const int N = 500001; int n,m,s; int depth[N], Log[N]; -int dbl[N][20]; // +int dbl[N][20]; //倍增数组 int tot; vector graph[N]; @@ -14,20 +14,20 @@ void dfs(int cur, int fa) { } int lca(int x,int y) { - // ͬһ߶ȣһ + // 把两个点升至同一高度,再一起跳 // TODO if(x==y) return x; - // ͬʱLCAһΪֹ + // 两个点同时往上跳,跳到LCA的下一层为止 // TODO return dbl[x][0]; } /* -㷨ʱ临ӶO(nlogn) +倍增算法时间复杂度是O(nlogn) */ int main() { scanf("%d%d%d",&n,&m,&s); @@ -36,9 +36,9 @@ int main() { scanf("%d%d",&x,&y); //todo } - dfs(s,0); // + dfs(s,0); // 建树 - // ԤŻ + // 预处理,常数优化 for(int i=2; i<=n; i++) { //todo } diff --git a/20240919/CSP常考算法模板/RMQ.cpp b/20240919/CSP常考算法模板/RMQ.cpp index 28baf7c..4984c40 100644 --- a/20240919/CSP常考算法模板/RMQ.cpp +++ b/20240919/CSP常考算法模板/RMQ.cpp @@ -4,7 +4,7 @@ using namespace std; const int N = 1e6 + 5; const int LOGN = 20; -int Log[N] = {-1}, f[N][LOGN + 1], a[N]; // f[i][j] 洢[i, i+2^j-1]ֵ֮ +int Log[N] = {-1}, f[N][LOGN + 1], a[N]; // f[i][j] 存储[i, i+2^j-1]之间的最值 int n, m; int main() { @@ -18,11 +18,11 @@ int main() { for(int i=1; i<=n; ++i) { f[i][0]=a[i]; - Log[i]=Log[i>>1] + 1; // ԤΪ1~nlogֵ + Log[i]=Log[i>>1] + 1; // 预处理出长度为1~n的log值 } - for(int j=1; j<=LOGN; j++) { // עj - for(int i=1; i+(1< using namespace std; -bool book[10]; //falseʾûù +bool book[10]; //false表示没用过 int a[10]; void print() diff --git a/20240919/CSP常考算法模板/区间dp/区间dp_合并石子.cpp b/20240919/CSP常考算法模板/区间dp/区间dp_合并石子.cpp index ebc6bbf..d280339 100644 --- a/20240919/CSP常考算法模板/区间dp/区间dp_合并石子.cpp +++ b/20240919/CSP常考算法模板/区间dp/区间dp_合并石子.cpp @@ -5,14 +5,14 @@ int a[101]; int sum[101]; // prefix sum int f[101][101]; /* -䶯̬滮ⲽ裺 -1.Ʋdp[i][j]ĺ -ǣѵ1ѵnʯӺϳһѣСĵ÷ -dp[i][j]ĺ壺ѵiѵjʯӺϳһѣСĵ÷ -2.ݹƳdp[i][j]״̬תƹʽ -i-j֮ѡһмֵk +区间动态规划解题步骤: +1.根据问题推测dp[i][j]的含义 +问题是:把第1堆到第n堆石子合成一堆,最小的得分 +dp[i][j]的含义:把第i堆到第j堆石子合成一堆,最小的得分 +2.根据规则推出dp[i][j]的状态转移公式 +在i-j之间选一个中间值k, dp[i][j]=dp[i][k]+dp[k+1][j]+(sum[j]-s[i-1]); -3.߽⣨趨dp[0][0],dp[0][j],dp[i][0],dp[i][j],dp[i][i]ʼֵ +3.边界问题(比如设定dp[0][0],dp[0][j],dp[i][0],dp[i][j],dp[i][i]初始值) */ @@ -41,7 +41,7 @@ int main() { sum[i] = sum[i-1] + a[i]; } - for(int i=n-1; i>=1; i--) { //һҪ + for(int i=n-1; i>=1; i--) { //一定要逆序 for(int j=i+1; j<=n; j++) { f[i][j] = INT_MAX; for(int k=i; k<=j-1; k++) { diff --git a/20240919/CSP常考算法模板/快速幂.cpp b/20240919/CSP常考算法模板/快速幂.cpp index a929796..8004647 100644 --- a/20240919/CSP常考算法模板/快速幂.cpp +++ b/20240919/CSP常考算法模板/快速幂.cpp @@ -4,8 +4,8 @@ using namespace std; int b, p, k; /* -ԭa*b%k=(a%k)*(b%k)%k -κһȻp=2*(p/2)+p%2 +原理:a*b%k=(a%k)*(b%k)%k +对于任何一个自然数:p=2*(p/2)+p%2 */ int f(int p) { if(p==0) // b^0%k @@ -13,7 +13,7 @@ int f(int p) { int t=f(p/2)%k; t=(t*t)%k; // b^p%k=(b^(p/2))^2%k if(p%2==1) - t=(t*b)%k; // pΪb^p%k=((b^(p/2))^2)*b%k + t=(t*b)%k; // 如果p为奇数,则b^p%k=((b^(p/2))^2)*b%k return t; } diff --git a/20240919/CSP常考算法模板/最小生成树/最小生成树_Prim(稠密图)..cpp b/20240919/CSP常考算法模板/最小生成树/最小生成树_Prim(稠密图)..cpp index 80f6335..aedb674 100644 --- a/20240919/CSP常考算法模板/最小生成树/最小生成树_Prim(稠密图)..cpp +++ b/20240919/CSP常考算法模板/最小生成树/最小生成树_Prim(稠密图)..cpp @@ -9,7 +9,7 @@ int dis[101]; int ans, cnt; vector graph[101]; bool visit[101]; -struct cmp //º +struct cmp // { bool operator()(const edge &a, const edge &b) { return a.w > b.w; diff --git a/20240919/CSP常考算法模板/最小生成树/最小生成树_kruskal(稀疏图).cpp b/20240919/CSP常考算法模板/最小生成树/最小生成树_kruskal(稀疏图).cpp index bc4adfb..6c38334 100644 --- a/20240919/CSP常考算法模板/最小生成树/最小生成树_kruskal(稀疏图).cpp +++ b/20240919/CSP常考算法模板/最小生成树/最小生成树_kruskal(稀疏图).cpp @@ -13,7 +13,7 @@ bool cmp(edge x, edge y) { } //int getDistance(int x1, int y1, int x2, int y2) { -// return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); // Ҫƽ +// return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); // 最后要求距离的平方 //} int n, m; @@ -27,7 +27,7 @@ void merge(int x, int y) { int fx = find(x); int fy = find(y); if (fx != fy) { - //һ + //如果不在一个集合 f[fy] = fx; } } @@ -59,7 +59,7 @@ int main() { for (int j = 1; j <= m; j++) { cin>>a[j].x>>a[j].y>>a[j].w; } - sort(a + 1, a + m + 1, cmp); // + sort(a + 1, a + m + 1, cmp); //排序 kruskal(); cout << ans << endl; return 0; diff --git a/20240919/CSP常考算法模板/最短路径/单源最短路径Dijkstra.cpp b/20240919/CSP常考算法模板/最短路径/单源最短路径Dijkstra.cpp index c4ee647..166b63e 100644 --- a/20240919/CSP常考算法模板/最短路径/单源最短路径Dijkstra.cpp +++ b/20240919/CSP常考算法模板/最短路径/单源最短路径Dijkstra.cpp @@ -15,10 +15,10 @@ int rs, re, ci; int dis[N]; bool vis[N]; -struct cmp //º +struct cmp //仿函数 { bool operator()(point a, point b) { - return a.len > b.len; //priority_queuesortĹ෴ + return a.len > b.len; //priority_queue的排序规则与sort的规则相反 } }; @@ -27,11 +27,11 @@ priority_queue, cmp> pq; void Dijkstra() { memset(dis, 0x3f, sizeof(dis)); - dis[ts] = 0; // ע ʼts + dis[ts] = 0; // 注意起 始点是ts!!! pq.push({ts, 0}); while (pq.size()>0) { - int id = pq.top().id; // ȡǰԴĵ + int id = pq.top().id; // 取出当前距离源点最近的点 pq.pop(); if (vis[id]) continue; diff --git a/20240919/CSP常考算法模板/最短路径/单源最短路径SPFA(有负边).cpp b/20240919/CSP常考算法模板/最短路径/单源最短路径SPFA(有负边).cpp index 776a56f..ee2cdcb 100644 --- a/20240919/CSP常考算法模板/最短路径/单源最短路径SPFA(有负边).cpp +++ b/20240919/CSP常考算法模板/最短路径/单源最短路径SPFA(有负边).cpp @@ -1,7 +1,7 @@ #include using namespace std; int dis[2501]; -bool exist[2501];//ÿǷqueue +bool exist[2501];//标记每个点是否在queue中 struct point { int to; @@ -13,7 +13,7 @@ vector graph[2501]; void SPFA() { memset(dis, 0x3f, sizeof(dis)); - dis[s] = 0; // ע ʼs + dis[s] = 0; // 注意起 始点是s!!! queue q; q.push(s); exist[s]=1; diff --git a/20240919/CSP常考算法模板/最短路径/多源最短路径Floyed.cpp b/20240919/CSP常考算法模板/最短路径/多源最短路径Floyed.cpp index 605fcae..0e15bf0 100644 --- a/20240919/CSP常考算法模板/最短路径/多源最短路径Floyed.cpp +++ b/20240919/CSP常考算法模板/最短路径/多源最短路径Floyed.cpp @@ -12,20 +12,20 @@ int main() for (i = 1; i <= n; i++) cin >> a[i][1] >> a[i][2]; cin >> m; - memset(f,0x7f,sizeof(f)); //ʼfΪֵ + memset(f,0x7f,sizeof(f)); //初始化f数组为最大值 - //Ԥxy + //预处理出x、y间距离 // for (i = 1; i <= m; i++) // { // cin >> x >> y; // f[y][x] = f[x][y] = sqrt(pow(a[x][1]-a[y][1],2)+pow(a[x][2]-a[y][2],2)); -// //pow(x,y)ʾx^yx,yΪdoubleͣҪcmath +// //pow(x,y)表示x^y,其中x,y必须为double类型,要用cmath库 // } for (i = 1; i <= n; i++) f[i][i]=0; cin >> s >> e; - for (k = 1; k <= n; k++) //kʾת //floyed ·㷨 + for (k = 1; k <= n; k++) //k表示中转点 //floyed 最短路算法 { for (i = 1; i <= n; i++) { diff --git a/20240919/CSP常考算法模板/树上问题_dfs.cpp b/20240919/CSP常考算法模板/树上问题_dfs.cpp index 5a916c1..c2329a4 100644 --- a/20240919/CSP常考算法模板/树上问题_dfs.cpp +++ b/20240919/CSP常考算法模板/树上问题_dfs.cpp @@ -3,16 +3,16 @@ using namespace std; const int MAXN = 1e5 + 5; -//dep[u]u -//leaf[u]uΪУdzǸҶӽڵȡ +//dep[u]代表u的深度 +//leaf[u]代表以u为根的子树中,深度最浅的那个叶子节点的深度。 int n , m , rt , leaf[MAXN] , dep[MAXN]; vector graph[MAXN]; -// dep[u]leaf[u] -int dfs(int u, int fa) { // ؾuҶӽڵ +// 算出dep[u]和leaf[u] +int dfs(int u, int fa) { // 返回距离u点最近的叶子节点深度 dep[u] = dep[fa] + 1; - // uҶӽڵ + // u是叶子节点 if(graph[u].size()==1) { leaf[u] = dep[u]; return leaf[u]; @@ -25,7 +25,7 @@ int dfs(int u, int fa) { // return leaf[u]; } -// ڵuܹfarmer +// 节点u能够被控制所需的farmer数量 int dfs2(int u, int fa) { if(dep[u] - 1 >= leaf[u] - dep[u]) return 1; int cnt = 0; diff --git a/20240919/CSP常考算法模板/线性dp_求最长不下降序列_逆推.cpp b/20240919/CSP常考算法模板/线性dp_求最长不下降序列_逆推.cpp index b03762a..5ad07f2 100644 --- a/20240919/CSP常考算法模板/线性dp_求最长不下降序列_逆推.cpp +++ b/20240919/CSP常考算法模板/线性dp_求最长不下降序列_逆推.cpp @@ -7,7 +7,7 @@ int a[100], dp[100], trace[100]; 14 13 7 9 16 38 24 37 18 44 19 21 22 63 15 - +输出 max=8 7 9 16 18 19 21 22 63 */ @@ -17,12 +17,12 @@ int main() cin>>n; for(int i=1; i<=n; i++) { - cin>>a[i]; // ԭʼ + cin>>a[i]; // 原始数据 dp[i]=1; // LIS - trace[i]=0; // һλ + trace[i]=0; // 上一个数的位置 } - // LIS + // 求LIS for(int i=n-1; i>=1; i--) { int maxlis=0; @@ -51,7 +51,7 @@ int main() } cout<<"max="<> 1; // ൱ (l + r) >> 1 k + int mid = l + r >> 1; // 相当于 (l + r) >> 1 k int lc = k << 1, rc = lc | 1; - build(lc, l, mid); // - build(rc, mid + 1, r); // + build(lc, l, mid); // 左子树 + build(rc, mid + 1, r); // 右子树 tree[k].w = tree[lc].w + tree[rc].w; } -// ޸ +// 单点修改 inline void changePoint(int k, int x, int c) { - if (tree[k].l == tree[k].r) { // ҵҶӽڵ + if (tree[k].l == tree[k].r) { // 找到叶子节点 tree[k].w += c; return; } @@ -40,7 +40,7 @@ inline void changePoint(int k, int x, int c) { tree[k].w = tree[lc].w + tree[rc].w; } -// ѯ +// 区间查询 inline LL queryInterval(int k, int L, int R) { if (tree[k].l >= L && tree[k].r <= R) return tree[k].w; diff --git a/20240919/CSP常考算法模板/背包问题_01.cpp b/20240919/CSP常考算法模板/背包问题_01.cpp index 466d5d7..4e0e796 100644 --- a/20240919/CSP常考算法模板/背包问题_01.cpp +++ b/20240919/CSP常考算法模板/背包问题_01.cpp @@ -17,16 +17,16 @@ int main(){ ios::sync_with_stdio(false); cin.tie(0); - cin>>m>>n; //mƷn - for (int i = 1; i <= n; i++) //ڳʼѭ֣һʼ - cin>>w[i]>>c[i]; //ÿƷͼֵ - for (int i = 1; i <= n; i++) // f[i][v]ʾǰiƷvżֵ + cin>>m>>n; //背包容量m和物品数量n + for (int i = 1; i <= n; i++) //在初始化循环变量部分,定义一个变量并初始化 + cin>>w[i]>>c[i]; //每个物品的重量和价值 + for (int i = 1; i <= n; i++) // f[i][v]表示前i件物品,总重量不超过v的最优价值 for (int v = m; v > 0; v--) if (w[i] <= v) f[i][v] = max(f[i-1][v],f[i-1][v-w[i]]+c[i]); else f[i][v] = f[i-1][v]; - cout<=t) { - v[++n1]=x*t; //൱n1++; v[n1]=x*t; + v[++n1]=x*t; //相当于n1++; v[n1]=x*t; w[n1]=y*t; s-=t; t*=2; } - //s2ֶָѣ1242^(k-1)s-2^k+1, + //把s以2的指数分堆:1,2,4,…,2^(k-1),s-2^k+1, if(s>0) { v[++n1]=x*s; w[n1]=y*s; diff --git a/20240919/CSP常考算法模板/背包问题_完全.cpp b/20240919/CSP常考算法模板/背包问题_完全.cpp index ea62b7b..e35544d 100644 --- a/20240919/CSP常考算法模板/背包问题_完全.cpp +++ b/20240919/CSP常考算法模板/背包问题_完全.cpp @@ -7,14 +7,14 @@ int f[maxm]; int main() { - scanf("%d%d",&m,&n); //mƷn + scanf("%d%d",&m,&n); //背包容量m和物品数量n for(i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]); for(i=1;i<=n;i++) - for(v=w[i];v<=m;v++) // f[v]ʾvֵ + for(v=w[i];v<=m;v++) //设 f[v]表示重量不超过v公斤的最大价值 if(f[v-w[i]]+c[i]>f[v]) f[v]=f[v-w[i]]+c[i]; - printf("max=%d\n",f[m]); // f[m]ΪŽ + printf("max=%d\n",f[m]); // f[m]为最优解 return 0; }