EOJ刷题记录第四弹
Problem #3369 - ECNU Online Judge
注意边数,意识到了使用邻接表,但是边数是二倍忘记考虑
1 | #include <iostream> |
Problem #3367 - ECNU Online Judge
第一眼是前缀和-差分数组问题,维护一个数组chazhi[N],定义为0-1的个数。
1 | // 错误思路,TLE |
最大子数组和 有一个非常经典的 O(n) 算法,叫做 Kadane’s Algorithm ( Kadane算法 )
- Kadane 算法要解决什么问题? (很明显,就是最大子数组和问题)
- Kadane 算法的核心思想是什么? (动态规划?贪心? 仔细体会它的递推关系)
- Kadane 算法的时间复杂度是多少? (O(n),非常高效)
- 如何用代码实现 Kadane 算法? (C/C++ 代码并不复杂)
学习 Kadane 算法之后,你就会发现,它可以非常漂亮地解决我们当前的问题。 只需要把原始数组转换成 [1, -1, -1, 1, 1, 1, …] 这种形式,然后用 Kadane 算法求最大子数组和,再加上原始数组中 1 的数量,就是最终答案!
3. 算法步骤 (Step-by-Step Logic)
假设输入数组为 arr,长度为 n。
- 初始化:
- global_maximum = arr[0] (或者负无穷,如果数组可能全为负数)
- current_maximum = arr[0] (或者 0,如果允许空子数组,但本题要求至少翻转一条咸鱼,所以子数组不能为空,这里初始化为第一个元素更合适)
- 迭代数组 (从第二个元素开始,索引从 1 到 n-1):
- 对于每个元素 arr[i]:
- current_maximum = max(arr[i], current_maximum + arr[i]) // 关键步骤:更新 current_maximum
- global_maximum = max(global_maximum, current_maximum) // 更新 global_maximum
- 返回 global_maximum
推荐题目列表:
- 题目名称: 最大子矩阵和 (Maximum Submatrix Sum)
- 简要描述: 给定一个二维矩阵,找到一个子矩阵,使其元素之和最大。
- 解题思路提示: 可以将二维问题降维到一维,枚举子矩阵的上下边界,然后将每一列的子矩阵部分求和,转化为一维的最大子数组和问题。 可以使用 Kadane’s Algorithm 解决一维子问题。
- 预期学习效果: 掌握将一维 DP 思想扩展到二维问题的技巧,加深对 Kadane’s Algorithm 的理解。
- 题目名称: 环形子数组最大和 (Maximum Sum Circular Subarray)
- 简要描述: 给定一个环形数组,找到一个子数组,使其元素之和最大。环形数组意味着数组的最后一个元素和第一个元素是相邻的。
- 解题思路提示: 环形数组的最大子数组和,要么是普通子数组的最大和 (不跨越环形边界),要么是跨越环形边界的子数组和。 可以分别计算这两种情况,取最大值。 跨越环形边界的子数组和,可以转换为 数组总和 减去 最小子数组和。
- 预期学习效果: 学习如何处理环形数组问题,掌握将问题分解为不同情况进行讨论的技巧。
- 题目名称: 乘积最大子数组 (Maximum Product Subarray)
- 简要描述: 给定一个整数数组,找到一个非空的连续子数组,使其乘积最大。
- 解题思路提示: 与最大子数组和类似,但需要同时维护最大值和最小值。 因为负数的存在,最小值乘以负数可能变成最大值。 状态转移时需要考虑当前元素、之前的最大值和最小值。
- 预期学习效果: 学习如何处理乘积最大化问题,理解负数对最大值的影响,扩展动态规划的应用场景。
用DP考虑
步骤
- 状态怎么表示
- 状态怎么转移
- dp数组怎么初始化