AcWing算法基础课题解目录

第一讲 基础算法

快速排序88

\(AcWing\) \(785\). 快速排序

\(AcWing\) \(786\). 第\(k\)个数

归并排序

\(AcWing\) \(787\). 归并排序

\(AcWing\) \(788\). 逆序对的数量

二分

\(AcWing\) \(789\). 数的范围

\(AcWing\) \(790\). 数的三次方根

高精度

\(AcWing\) \(791\). 高精度加法

\(AcWing\) \(792\). 高精度减法

\(AcWing\) \(793\). 高精度乘法

\(AcWing\) \(794\). 高精度除法

前缀和与差分

\(AcWin\)g \(795\). 前缀和

\(AcWing\) \(796\). 子矩阵的和

前缀和专题

\(AcWing\) \(797\). 差分

\(AcWing\) \(798\). 差分矩阵

差分专题

双指针算法

\(AcWing\) \(799\). 最长连续不重复子序列

\(AcWing\) \(800\). 数组元素的目标和

\(AcWing\) \(2816\). 判断子序列

位运算

\(AcWing\) \(801\). 二进制中\(1\)的个数

离散化

\(AcWing\) \(802\). 区间和

区间合并

\(AcWing\) \(803\). 区间合并

第二讲 数据结构

单链表

\(AcWing\) \(826\). 单链表

双链表

\(AcWing\) \(827\). 双链表

\(AcWing\) \(828\). 模拟栈

\(AcWing\) \(3302\). 表达式求值

队列

\(AcWing\) \(829\). 模拟队列

单调栈

\(AcWing\) \(830\). 单调栈

单调队列

\(AcWing\) \(154\). 滑动窗口

KMP

\(AcWing\) \(831\). \(KMP\)字符串

Trie

\(AcWing\) \(835\). \(Trie\)字符串统计

\(AcWing\) \(143\). 最大异或对

并查集

\(AcWing\) \(836\). 合并集合

\(AcWing\) \(837\). 连通块中点的数量

\(AcWing\) \(240\). 食物链

\(AcWing\) \(838\). 堆排序

\(AcWing\) \(839\). 模拟堆

哈希表

\(AcWing\) \(840\). 模拟散列表

\(AcWing\) \(841\). 字符串哈希

第三讲 搜索与图论

DFS

\(AcWing\) \(842\). 排列数字

\(AcWing\) \(843\). \(n\)-皇后问题

BFS

\(AcWing\) \(844\). 走迷宫

\(AcWing\) \(845\). 八数码

树与图的深度优先遍历

\(AcWing\) \(846\). 树的重心

树与图的广度优先遍历

\(AcWing\) \(847\). 图中点的层次

拓扑排序

\(AcWing\) \(848\). 有向图的拓扑序列

Dijkstra

\(AcWing\) \(849\). \(Dijkstra\)求最短路\(I\)

\(AcWing\) \(850\). \(Dijkstra\)求最短路\(II\)

bellman-ford

\(AcWing\) \(853\). 有边数限制的最短路

spfa

\(AcWing\) \(851\). \(spfa\)求最短路

\(AcWing\) \(852\). \(spfa\)判断负环

Floyd

\(AcWing\) \(854\). \(Floyd\)求最短路

Prim

\(AcWing\) \(858\). \(Prim\)算法求最小生成树

Kruskal

\(AcWing\) \(859\). \(Kruskal\)算法求最小生成树

染色法判定二分图

\(AcWing\) \(860\). 染色法判定二分图

匈牙利算法[月佬算法]

\(AcWing\) \(861\). 二分图的最大匹配

第四讲 数学知识

质数

\(AcWing\) \(866\). 试除法判定质数

\(AcWing\) \(867\). 分解质因数

\(AcWing\) \(868\). 筛质数

约数

\(AcWing\) \(869\). 试除法求约数

\(AcWing\) \(870\). 约数个数

\(AcWing\) \(871\). 约数之和

\(AcWing\) \(872\). 最大公约数

欧拉函数

\(AcWing\) \(873\). 欧拉函数

\(AcWing\) \(874\). 筛法求欧拉函数

快速幂

\(AcWing\) \(875\). 快速幂

\(AcWing\) \(876\). 快速幂求逆元

扩展欧几里得算法

\(AcWing\) \(877\). 扩展欧几里得算法

\(AcWing\) \(878\). 线性同余方程

中国剩余定理

\(AcWing\) \(204\). 表达整数的奇怪方式

高斯消元

\(AcWing\) \(883\). 高斯消元解线性方程组

\(AcWing\) \(884\). 高斯消元解异或线性方程组

求组合数

\(AcWing\) \(885\). 求组合数 I

\(AcWing\) \(886\). 求组合数 II

\(AcWing\) \(887\). 求组合数 III

\(AcWing\) \(888\). 求组合数 IV

\(AcWing\) \(889\). 满足条件的01序列

容斥原理

\(AcWing\) \(890\). 能被整除的数

博弈论

\(AcWing\) \(891\). \(Nim\) 游戏

\(AcWing\) \(892\). 台阶-\(Nim\)游戏

\(AcWing\) \(893\). 集合-\(Nim\)游戏

\(AcWing\) \(894\). 拆分-\(Nim\)游戏

第五讲 动态规划

背包问题

\(AcWing\) \(2. 01\)背包问题

\(AcWing\) \(3\). 完全背包问题

\(AcWing\) \(4\). 多重背包问题

\(AcWing\) \(5\). 多重背包问题 II

\(AcWing\) \(9\). 分组背包问题

线性DP

\(AcWing\) \(898\). 数字三角形

\(AcWing\) \(895\). 最长上升子序列

\(AcWing\) \(896\). 最长上升子序列 II

\(AcWing\) \(897\). 最长公共子序列

\(AcWing\) \(902\). 最短编辑距离

\(AcWing\) \(899\). 编辑距离

区间DP

\(AcWing\) \(282\). 石子合并

计数类DP

\(AcWing\) \(900\). 整数划分

数位统计DP

\(AcWing\) \(338\). 计数问题

状态压缩DP

\(AcWing\) \(291\). 蒙德里安的梦想

\(AcWing\) \(91\). 最短\(Hamilton\)路径

树形DP

\(AcWing\) \(1049\). 大盗阿福 [没有上司的舞会 引入题]

\(AcWing\) \(285\). 没有上司的舞会

记忆化搜索

\(AcWing\) \(901\). 滑雪

第六讲 贪心

区间问题


\(AcWing\) \(905\). 区间选点
思路:尽可能让选择的点跨更多的区间。

\(AcWing\) \(908\). 最大不相交区间数量
思路:最大不相交区间数量与区间选点是一样的代码,因为如果某些线段有公共的点,那么它们只能取一个,换句话说,就是有距离无交叉的区间个数。


\(AcWing\) \(906\). 区间分组

\(AcWing\) \(907\). 区间覆盖

Huffman树

\(AcWing\) \(148\). 合并果子

排序不等式

\(AcWing\) \(913\). 排队打水

绝对值不等式

\(AcWing\) \(104\). 货仓选址

推公式

\(AcWing\) \(114\) 国王游戏

\(AcWing\) \(125\). 耍杂技的牛

posted @ 2021-10-11 14:44  糖豆爸爸  阅读(226)  评论(1编辑  收藏  举报

【算法竞赛】背包问题

01背包:

问题描述:

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

第 i 件物品的体积是 Vi,价值是 Wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

问题分析:

为方便描述, 第i件物品的体积v, 价值w 分别记成 目标分量goal (简记gl)约束分量limit(简记lmt); 容量V 记成 最大约束总量lmt_max

//问题描述
struct bag{
	int gl, lmt;        //目标分量goal, 约束分量limit 
}b[maxn];
int n, lmt_max        //物品数, 最大约束总量

大问题:f(n, lmt_max)

小问题:max{ f(n-1, lmt_max - k*lmt) }, k = 0, 1

定义dp[i][j]:考虑前 i 个物品, 约束值 不超过 j 的 最大目标函数值

转态转移方程:dp[i][j] = max{ dp[i-k][j - k*lmt] + k*gl }, k = 0 或 (k = 1 && j >= lmt)

                                  或= max{ dp[i-1][j], dp[i-1][j - lmt] + gl }

//O(n^2)
int dp[maxn][maxn];
int f(){
	for(int i=1; i<=n; i++){
		for(int j=1; j<=lmt_max; j++){
			if(j >= b[i].lmt){
				dp[i][j] = max(dp[i-1][j], dp[i-1][j-b[i].lmt] + b[i].gl);
			}
			else dp[i][j] = dp[i-1][j];
		}
	}
	return dp[n][lmt_max];
}

滚动数组优化(空间复杂度优化):

可以观察到每个状态都跟 上层的左边两个状态 有关(如图)

 如果把dp数组第一维压缩成“一点”(空间复杂度降1阶),新的状态应与左边的状态有关(如图)

此时应考虑一个问题:是从左往右递推, 还是从右往左?

如果从左往右递推, 假设左边的状态已通过该方式更新,那么新状态是通过该层的状态更新的, 与递推关系矛盾(因为每个状态都跟 (逻辑上的)上层的左边两个状态 有关),其原因是在递推时(逻辑上的)上层的被覆盖了, 因此从左往右不可行

考虑从右往左递推, 每个新状态都是跟(逻辑上的)上层左边的状态有关, 递推的新状态与前面的新状态没有影响, 因此采用从右往左递推

//O(n^2)
int dp[1005];
int f(){
	for(int i=1; i<=n; i++){
		for(int j=lmt_max; j>=1; j--){
			if(j>=b[i].lmt)
				dp[j] = 
				max(dp[j], dp[j-b[i].lmt] + b[i].gl);
			else dp[j] = dp[j];        //可省略
		}
	}
	return dp[lmt_max];
}

完全背包:

问题描述:

有 N种物品和一个容量是 V 的背包,每种物品都有无限件可用

第 i 种物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

问题分析:

01背包 在选择是否加入 物品i (可以理解为选择 0个 或者 一个 物品i), 此状态是最优的

完全背包 与 01背包的主要区别就是, 在选择物品i时, 考虑加入k(=0..t)个物体i 时此状态是最优的

容易得出:

状态转移方程: dp[i][j] = max{ dp[i-1][j - k*lmt] }, k = 0..t && j >= t * lmt

//O(n^3)
int f(){
	for(int i=1; i<=n; i++){
		for(int j=1; j<=lmt_max; j++){
			for(int k=0; k*b[i].lmt<=j; k++){
				dp[i][j] = 
				max(dp[i][j], dp[i-1][j-k*b[i].lmt] + k*b[i].gl);
			}
		}
	}
	return dp[n][lmt_max];
}

完全背包优化:

然而O(n^3)的复杂度过大, 对于 8e3 的数据是不可行的

dp[i][j] = max{ dp[i-1][j - k*lmt] + k*gl }, k = 0..t

dp[i][j - lmt] = max{ dp[i-1][j - lmt - k*lmt] + k*gl }, k = 0..t-1

                     = max{ dp[i-1][j - (k+1)*lmt] + k*gl }, k = 0..t-1

dp[i][j - lmt] + gl = max{ dp[i-1][j - (k+1)*lmt] + (k+1)*gl }, k = 0..t-1

                            = max{ dp[i-1][j - k*lmt] + k*gl }, k = 1..t

那么, dp[i][j] = max{ dp[i-1][j - k*lmt] + k*gl }, k = 0..t

                        = max{ dp[i-1][j],   [max{ dp[i-1][j - k*lmt] + k*gl }, k = 1..t] }

                        = max{ dp[i-1][j], dp[i][j-lmt] + gl }

可以观察到, 优化后完全背包的状态方程与 01背包的状态方程 仅有一个下标的不同, 而且复杂度降为了O(n^2)

//O(n^2)
int f(){
	for(int i=1; i<=n; i++){
		for(int j=1; j<=lmt_max; j++){
			if(j >= b[i].lmt)
				dp[i][j] = 
				max(dp[i-1][j], dp[i][j-b[i].lmt] + b[i].gl);
			else dp[i][j] = dp[i-1][j];
		}
	}
	return dp[n][lmt_max];
}

更新中...

posted @ 2022-02-20 13:33  ldMCA  阅读(151)  评论(0)    收藏  举报