1 条题解
-
0
D. Shift + Esc 题解
题目大意
给定 行 列的非负整数网格,你从 出发,只能向下/向右移动到 。 在移动前,你可以对任意行执行任意次循环左移1位操作:
- 对第 行左移 次,代价为 ;
- 移动后路径经过的单元格数值和为 ;
- 总代价 = 操作总代价 + 路径和。
求最小总代价。
约束:,所有测试用例 ,数值范围可达 。
核心思路
关键观察
- 移动特性:从起点到终点,每行只会停留一个最终列位置(从上行下移到当前行后,只能向右走,最终停在某一列,再下移到下一行)。
- 循环移位:一行左移 次等价于不移位,因此每行只需枚举 次移位即可。
- 动态规划:用DP记录「处理完前 行,停在第 行第 列」的最小代价,完美适配问题的无后效性。
状态定义
:处理完前 行,最终停在第 行第 列的最小总代价。
状态转移
- 枚举第 行的移位次数 ();
- 从第 行的任意列转移而来,加上当前行移位代价 + 路径数值和;
- 利用行内只能向右移动的特性,用两次环形遍历优化区间最小值转移。
完整AC代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; // 数组开至511,满足n,m<=200的约束 ll dp[511][511], a[511][511]; void solve() { int n, m, k; cin >> n >> m >> k; // 输入网格,下标从1开始(行)、0开始(列)方便取模运算 for (int i = 1; i <= n; ++i) { for (int j = 0; j < m; ++j) { cin >> a[i][j]; } } // 初始化DP数组为无穷大(1e18 避免long long溢出) for (int i = 0; i <= n; ++i) { for (int j = 0; j < m; ++j) { dp[i][j] = 1e18; } } dp[0][0] = 0; // 初始状态:第0行第0列,代价为0 // 逐行处理 for (int i = 1; i <= n; ++i) { // 枚举当前行的循环左移次数 shift (0~m-1) for (int shift = 0; shift < m; ++shift) { vector<ll> tmp(m, 1e18); // 第一步:从i-1行转移,加上当前列的值 + 移位代价 for (int j = 0; j < m; ++j) { tmp[j] = dp[i-1][j] + a[i][(j + shift) % m] + 1LL * k * shift; } // 两次环形遍历更新最小值:行内只能向右走,递推最小代价 for (int j = 0; j < m; ++j) { tmp[j] = min(tmp[j], tmp[(j + m - 1) % m] + a[i][(j + shift) % m]); } for (int j = 0; j < m; ++j) { tmp[j] = min(tmp[j], tmp[(j + m - 1) % m] + a[i][(j + shift) % m]); } // 更新当前行的DP值 for (int j = 0; j < m; ++j) { dp[i][j] = min(dp[i][j], tmp[j]); } } } // 答案:第n行最后一列的最小代价 cout << dp[n][m-1] << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }
代码详解
1. 初始化
dp数组初始化为 (无穷大),代表初始状态不可达;dp[0][0] = 0:虚拟的第0行第0列,作为起点。
2. 逐行枚举移位
对每一行 ,枚举所有可能的移位次数 :
- 计算基础代价:上一行的代价 + 当前单元格数值 + 移位代价;
- 两次环形遍历:利用只能向右移动的规则,递推求出当前行所有列的最小代价(等价于区间最小值优化)。
3. 答案输出
终点是第 行最后一列,对应下标
dp[n][m-1]。
复杂度分析
- 时间复杂度:
- ,单组用例 ;
- 总数据量 ,完全满足时间限制。
- 空间复杂度:,数组大小完全适配题目约束。
优化说明
- 数据类型:全程使用
long long,避免 数值相加溢出; - 输入优化:加
ios::sync_with_stdio(false);cin.tie(nullptr);加速大数据输入; - 移位枚举:仅枚举 次,避免无效计算。
- 1
信息
- ID
- 7206
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者