2020 方格取数 · 方案二 按列动态规划
三状态分别记从上方、下方、左方到达
正文
// CSP-J 2020 复赛 T4 · 方格取数(方案二 · 满分)
// 原题:https://oj.yecheng.tv/p/CSPJ2020D
//
// 方案二 · 按列动态规划
// 突破口在「只能向右、向上、向下」:这意味着一旦离开某一列就再也回不去,
// 而在同一列里,人只能沿着一个方向一直走(先向下就不会再向上,否则会撞回走过的格子)。
// 于是把「怎么到达 (i, j)」分成三种状态:
// dp[i][j][0] 从上方来(在本列里一路向下走到 (i, j))
// dp[i][j][1] 从下方来(在本列里一路向上走到 (i, j))
// dp[i][j][2] 从左方来(刚从左边那一列跨过来)
// 转移也就清楚了:
// 向左跨过来:上一列三种状态取最大;
// 向下走:只能接「上一格也是向下来的」或「上一格是刚跨过来的」;
// 向上走:只能接「下一格也是向上来的」或「下一格是刚跨过来的」。
// 因为要先有「刚跨过来」的结果,每列的处理顺序固定为:先算 [2],再正着算 [0],再倒着算 [1]。
// 复杂度:O(n * m),空间 O(n * m * 3)。
#include <bits/stdc++.h>
using namespace std;
const long long NEG = -(1LL << 60);
static long long dp[1005][1005][3];
static long long a[1005][1005];
int main() {
freopen("number.in", "r", stdin);
freopen("number.out", "w", stdout);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) cin >> a[i][j];
}
for (int i = 0; i <= n + 1; i++) {
for (int j = 0; j <= m + 1; j++) {
dp[i][j][0] = dp[i][j][1] = dp[i][j][2] = NEG;
}
}
dp[1][1][0] = dp[1][1][1] = dp[1][1][2] = a[1][1];
for (int j = 1; j <= m; j++) {
if (j > 1) {
for (int i = 1; i <= n; i++) { // 从左边那一列跨过来
long long best = max(dp[i][j - 1][0], max(dp[i][j - 1][1], dp[i][j - 1][2]));
if (best != NEG) dp[i][j][2] = max(dp[i][j][2], best + a[i][j]);
}
}
for (int i = 2; i <= n; i++) { // 在本列里继续向下
long long best = max(dp[i - 1][j][0], dp[i - 1][j][2]);
if (best != NEG) dp[i][j][0] = max(dp[i][j][0], best + a[i][j]);
}
for (int i = n - 1; i >= 1; i--) { // 在本列里继续向上,必须倒着枚举
long long best = max(dp[i + 1][j][1], dp[i + 1][j][2]);
if (best != NEG) dp[i][j][1] = max(dp[i][j][1], best + a[i][j]);
}
}
cout << max(dp[n][m][0], max(dp[n][m][1], dp[n][m][2])) << "\n";
return 0;
}
CSP-J 标程 · 复赛真题的其它内容
- 2019 数字游戏 · 方案一 逐字符统计
- 2019 数字游戏 · 方案二 二进制位运算
- 2020 优秀的拆分 · 方案一 贪心从大到小减
- 2020 优秀的拆分 · 方案二 直接看二进制位
- 2021 分糖果 · 方案一 枚举每个 k
- 2021 分糖果 · 方案二 看余数在哪一段
- 2022 乘方 · 方案一 边乘边判断
- 2022 乘方 · 方案二 快速幂加封顶
- 2023 小苹果 · 方案一 照规则真模拟
- 2023 小苹果 · 方案二 只盯住两个数字
- 2024 扑克牌 · 方案一 用集合去重
- 2024 扑克牌 · 方案二 二维布尔表
- 2025 拼数 · 方案一 收集后降序排序
- 2025 拼数 · 方案二 桶计数
- 2019 公交换乘 · 方案一 暴力匹配
- 2019 公交换乘 · 方案二 时间窗口优化
- 2020 直播获奖 · 方案一 每轮排序
- 2020 直播获奖 · 方案二 桶计数
- 2021 插入排序 · 方案一 每次真排一遍
- 2021 插入排序 · 方案二 增量维护有序表
- 2022 解密 · 方案一 二分求整数平方根
- 2022 解密 · 方案二 先估后校开方
- 2023 公路 · 方案一 朴素贪心
- 2023 公路 · 方案二 单调栈预处理
- 2024 地图探险 · 方案一 四方向分支写
- 2024 地图探险 · 方案二 方向数组
- 2025 座位 · 方案一 把座位表填出来
- 2025 座位 · 方案二 直接算排名
- 2019 纪念品 · 方案一 逐天完全背包
- 2019 纪念品 · 方案二 砍掉不赚钱物品
- 2020 表达式 · 方案一 每次重算后缀式
- 2020 表达式 · 方案二 建树加关键性传播
- 2021 网络连接 · 方案一 手写解析
- 2021 网络连接 · 方案二 读入后回拼校验
- 2022 逻辑表达式 · 方案一 递归分治
- 2022 逻辑表达式 · 方案二 递归下降
- 2023 一元二次方程 · 方案一 照公式逐步写
- 2023 一元二次方程 · 方案二 拆成小函数
- 2024 小木棍 · 方案一 先定位数再贪心
- 2024 小木棍 · 方案二 预处理最小数字表
- 2025 异或和 · 方案一 贪心能接就接
- 2025 异或和 · 方案二 动态规划加值域数组
- 2019 加工零件 · 方案一 递归加记忆化
- 2019 加工零件 · 方案二 奇偶最短路
- 2020 方格取数 · 方案一 深搜回溯
- 2021 小熊的果篮 · 方案一 每轮扫一遍
- 2021 小熊的果篮 · 方案二 链表加有序集合
- 2022 上升点列 · 方案一 先只考虑不加点
- 2022 上升点列 · 方案二 二维动态规划
- 2023 旅游巴士 · 方案一 分层图加优先队列
- 2023 旅游巴士 · 方案二 状态压成一维
- 2024 接龙 · 方案一 按定义广搜
- 2024 接龙 · 方案二 滑动窗口逐轮推进
- 2025 多边形 · 方案一 枚举所有子集
- 2025 多边形 · 方案二 排序加计数 DP