这是一道经典但具有一定难度的棋盘模型题。虽然是 2000 年的 NOIP 题目,但作为压轴题,对于第一次接触的人来说还是相当困难的。本文总结了三种不同的解法:动态规划、DFS 记忆化和最小费用最大流,从易到难逐步展开。
问题
题目来源
NOIP 2000 提高组 T4
问题描述
设有 N×N 的方格图 (N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0。 某人从图的左上角的 A 点(0,0)出发,可以向下行走,也可以向右走,直到到达右下角的 B 点(N, N)。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0)。 此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。
输入输出
输入格式 :输入的第一行为一个整数 N(表示 N×N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 0 表示输入结束。
输出格式 :只需输出一个整数,表示 2 条路径上取得的最大的和。
样例
输入:
| |
输出:
| |
约束条件
- 数据范围:1≤N≤9
问题分析
为什么不能采取两次枚举(即先找一条最优路径,再在剩余格子中找第二条)?因为一次路径会改变地图(取走数字),影响第二次的结果,所以两条路径必须联动考虑,而不能独立优化。
思路分析
三种解法的思路分别如下:
解法一:动态规划
核心思想 :将两条路径同步推进,用一个 DP 同时模拟两个人的行走。
状态设计 :设 dp[k][x1][x2],其中:
- k 为当前走的步数(即 x + y 的值,从 2 到 2N)
- x1、x2 分别为两人当前所在的行号
- 由 k 和 x 可以推出 y = k - x(关键优化,这一步降低了维度),因此列号不需要单独存储
去重处理 :当两人在同一格时(x1 == x2,则 y1 == y2),该格只取一次。
状态转移 :每步两人各自可以选择向右或向下,共 4 种组合。每个状态 dp[k][x1][x2] 代表走到第 k 步,人 1 在行 x1、人 2 在行 x2 时的最大取数和。
解法二:DFS + 记忆化搜索
核心思想 :类似于 DP 算法(毕竟深搜和 DP 本质上就是一个东西),但添加了记忆化搜索来避免重复计算。若无记忆化搜索,计算量将是指数级爆炸,在 N=9 时约为 $4^{16}$ 次。
实现方式 :从初始状态出发,递归地尝试所有可能的转移,同时用 memo 数组缓存已计算过的状态,避免重复。在达到终点时返回 0,逐层返回最大值。
解法三:费用流(最小费用最大流)
核心思想 :将"两条路径取最大值"转化为网络流问题。
建模思路 :
- 两条从 A 到 B 的路径 = 从源点到汇点流量为 2 的流
- 每个格子最多取一次 = 每个节点容量限制
- 取得数字最大 = 费用最大(转为最小费用取负值)
拆点处理 :每个格子 (i,j) 拆成两个节点 in 和 out:
- in → out 容量 1,费用 -map[i][j](第一条路径取数)
- in → out 再加容量 1,费用 0(第二条路径经过但不取数)
连边 :(i,j) 的 out 连向 (i+1,j) 的 in 和 (i,j+1) 的 in,容量 2,费用 0。
代码实现
解法一:动态规划
完整代码
| |
解法二:DFS + 记忆化搜索
| |
解法三:费用流(最小费用最大流)
| |
时间复杂度与优缺点
解法一:动态规划
时间复杂度 :$O(N^3)$
- 状态数:$O(N^2) \times O(N^2) / 2 = O(N^4)$,但由于降维和 x1、x2 的约束,实际为 $O(N^3)$
- 每个状态有 4 次转移
空间复杂度 :$O(N^3)$
- dp 数组大小为 $2N \times N \times N$
优点 :
- 思路清晰,易于理解
- 一次遍历解决问题
- 代码相对简洁
缺点 :
- 空间占用较大(N=9 时约 1.3MB)
解法二:DFS + 记忆化搜索
时间复杂度 :$O(N^3)$
- 状态数与 DP 相同
- 每个状态最多计算一次(记忆化)
空间复杂度 :$O(N^3)$
- memo 和 visited 数组各占 $O(N^3)$
优点 :
- 逻辑自然,从上向下思考
- 易于添加剪枝(虽然此题中剪枝不多)
- 可灵活调整状态定义
缺点 :
- 递归调用栈深度为 $O(N)$(栈空间)
- 空间复杂度与 DP 相同
解法三:费用流
时间复杂度 :$O(Flow \times SPFA) = O(2 \times E \log V) = O(N^2 \times N^2) = O(N^4)$
- 流量为 2
- SPFA 每次 $O(V \log V)$,其中 $V = O(N^2)$,$E = O(N^2)$
空间复杂度 :$O(V + E) = O(N^2)$
- 图的存储空间
优点 :
- 适用于更一般的场景(多条路径、带限制的图等)
- 代码框架可复用于其他费用流问题
- 空间占用相对较少
缺点 :
- 时间复杂度最高(约 $O(N^4)$ vs $O(N^3)$)
- 代码长且复杂,易出错
- 难度陡升,超出竞赛难度范围
对比与总结
| 特性 | 解法一 DP | 解法二 DFS | 解法三 费用流 |
|---|---|---|---|
| 易理解度 | ★★★★☆ | ★★★★☆ | ★☆☆☆☆ |
| 实现难度 | ★★☆☆☆ | ★★☆☆☆ | ★★★★★ |
| 时间复杂度 | $O(N^3)$ | $O(N^3)$ | $O(N^4)$ |
| 空间复杂度 | $O(N^3)$ | $O(N^3)$ | $O(N^2)$ |
| 推荐指数 | ★★★★★ | ★★★★☆ | ★★☆☆☆ |
结论 :对于此题,解法一(DP) 是最佳选择,既清晰高效又不过度复杂。解法二适合想要练习 DFS 的同学。解法三虽然优雅,但对于 N≤9 的规模效率不如 DP,仅作扩展知识。
💬 评论