算法题模板
目录
Acwing算法基础课模板
排序
快速排序
|
|
归并排序
|
|
二分
整数二分
|
|
浮点数二分
|
|
高精度
高精度加法
|
|
高精度减法
|
|
高精度乘法
|
|
高精度除法
|
|
差分和前缀和
前缀和
|
|
差分
|
|
双指针
|
|
位运算
|
|
离散化
|
|
区间合并
|
|
数据结构
单链表
|
|
双链表
|
|
栈
|
|
队列
|
|
单调栈
|
|
单调队列
|
|
KMP
|
|
Trie数
|
|
并查集
|
|
堆
|
|
哈希表
|
|
STL
vector
|
|
pair
|
|
string
|
|
queue
|
|
priority_queue
|
|
stack
|
|
deque
|
|
set / multiset
|
|
map / multimap
|
|
unorder_set / unorder_multiset / unorder_map / unordered_multimap
|
|
bitset
|
|
动态规划
- 无后效性,动态规划要求求解的子问题不受后续阶段的影响。换言之,动态规划对状态空间的遍历构成一张有向无环图,遍历该有向无环图就是一个拓扑序,有向无环图中每个节点对应不同的状态,图中的边对应状态之间的转移。
背包问题
-
01背包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
//考虑前i个物品,且总体积不大于j的所有选法 int v[N], w[N]; int f[N][N]; for(int i = 1; i <= n; i++) { for(int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if(j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]); } } //优化 int f[N]; for(int i = 1; i <= n; i++) { for(int j = m; j >= w[i]; j--) { f[j] = max(f[j], f[j - v[i]] + w[i]); } }
-
完全背包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
for(int i = 1; i <= n; i++) for(int j = 0; j <= m; j++) for(int k = 0; k * v[i] <= j; k++) f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]) /*优化 f[i, j] = max(f[i - 1][j], f[i - 1][j - v] + w, f[i - 1][j - 2*v] + 2*w + .....) f[i, j -v] = max( f[i - 1][j - v], f[i - 1][j - 2* v]......) */ for(int i = 1; i <= n; i++) for(int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if(j >= v[i]) f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]); } //优化(区别于01背包的遍历顺序) for(int i = 1; i <= n; i++) { for(int j = v[i], j <= m; j++) { f[j] = max(f[j], f[j - v[i]] + w[i]); } }
-
多重背包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
//将多重背包转化为01背包(二进制优化) while(k <= s) { cnt++; v[cnt] = a * k; w[cnt] = b * k; s -= k; k *= 2; } if(s > 0) { cnt++; v[cnt] = a * s; w[cnt] = b * s; } n = cnt; for(int i = 1; i <= n; i++) { for(int j = m; j >= w[i]; j--) { f[j] = max(f[j], f[j - v[i]] + w[i]); } }
-
分组背包问题
1 2 3 4 5 6 7 8
for(int i = 0; i < n; i++) { for(int j = m; j >= 0; j--) { for(int k = 0; k < s[i]; k++) if(v[i]][k] <= j) f[j] = max(f[j], f[j - v[i][k]] + w[i][k]); } }
线性DP
-
数组三角形
-
最长上升子序列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
for(int i = 0; i < n; i++) { f[i] = 1; for(int j = 0; j < i; j++) { if(f[i] > f[j]) f[i] = max(f[i], f[j] + 1) } } //求路线 for(int i = 0; i < n; i++) { f[i] = 1; g[i] = 0; for(int j = 0; j < i; j++) { if(f[i] > f[j]) if(f[i] < f[j] + 1) { f[i] = f[j] + 1; g[i] = j; } } } for(int i = 0, len = f[k]; i < len; i++) { printf("%d", g[k]); k = g[k]; }
-
最长上升子序列II
1 2 3 4 5 6 7 8 9 10 11 12
for(int i = 0; i < n; i++) { int l = 0, r = len; while(l < r) { int mid = (l + r + 1) / 2; if(q[mid] < a[i]) l = mid; else r = mid - 1; } len = max(len, r + 1); q[r + 1] = a[i]; }
-
最长公共子序列
1 2 3 4 5 6 7 8
for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { f[i][j] = max(f[i - 1][j], f[i][j - 1]); if(a[i] == b[j]) f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1); } }
-
编辑距离
1 2 3 4 5 6 7 8 9 10 11 12
for(int i = 0; i <= m; i++) f[0][i] = i; for(int i = 0; i <= n; i++) f[i][0] = i; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { f[i][j] = min(f[i - 1][j], f[i][j - 1]); if(a[i] == b[j]) f[i][j] = min(f[i][j], f[i - 1][j - 1]); else f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1); } }
区间DP
-
石子合并
1 2 3 4 5 6 7 8 9 10 11 12
for(int len = 2; len <= n; len++) { for(int i = 1; i + len - 1<= n; i++) { int l = i, r = i + len - 1; f[i][j] = 1e8; for(int k = i, k < r; k++) { f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r] + s[r] - s[l - 1]); } } }
计数DP
-
整数划分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
//背包做法 f[i][j] = f[i - 1][j] + f[i - 1][j - i] + f[i - 1][j - 2i] +... f[i - 1][j - si]; f[i][j - 1] = f[i - 1][j - 1] + f[i - 1][j - 2i] +... f[i - 1][j - si]; f[i][j] = f[i - 1][j] + f[i][j - 1]; for(int i = 1; i <=n ;i++) for(int j = i; j <= n; j++) { f[j] = (f[j] + f[j - 1]) % mod; } //计数dp //集合:所有总和为i,并且恰好表示成j个数的和的方案 for(int i = 1; i <= n; i++) { for(int j = 1; j <= i; j++) { f[i][j] = (f[i - 1][j] + f[i - j][j]) % mod } } return f[n][1] + .....f[n][n];
数位DP
-
数字统计
搜索和图论
DFS
BFS
邻接表
|
|
拓扑排序
|
|
单源最短路
|
|
|
|
|
|
|
|
|
|
多源汇最短路
|
|
最小生成树
|
|
|
|
二分图
|
|
|
|
线段树
|
|