1 条题解
-
0
自动搬运
来自洛谷,原作者为

baiABC
AFOed搬运于
2025-08-24 21:41:42,当前版本为作者最后更新于2022-07-02 23:19:48,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这题网上都是清一色的 dfs,但是其实直接 dp 也可以。
设 表示 位置当前速度为 ,潜水时间为 的最大答案(本格得到的钱不计),则容易递推更新后继状态, 即为答案。
先解决空间问题。首先 一维可以用滚动数组,然后由于 ,所以 ,可以开下。 可能是负数,给 加上 变成正数。
再考虑时间,可以限制下一个阶段枚举的 的范围。时间复杂度 ,可以过。
DP 注意细节。
#include <bits/stdc++.h> using namespace std; int dp[2][105][605][15], a[105][1005][2]; void upd(int &x, int y) { x = max(x, y); } int main() { ios::sync_with_stdio(0); int n, m, k; cin >> n >> m >> k; for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) { char c; cin >> c; a[i][j][0] = c=='v'; cin >> a[i][j][1]; } memset(***dp, 0x80, sizeof dp); // -INF dp[1][1][300][0] = 0; // 下面 v 都加了 300 int lalv = 0, larv = 0, lv = 300, rv = -300; for(int i = 1; i < m; ++i) { int r = i & 1, tr = r^1; for(int j = 1; j <= n; ++j) { if(j == 1) { int ts = dp[r][1][300][0]; if(ts == 0x80808080) continue; if(!a[1][i][0]) ts += a[1][i][1]; lv = rv = 0; upd(dp[tr][1][300][0], ts); if(n > 1) upd(dp[tr][2][301][1], ts), rv = 1; continue; } for(int v = lalv; v <= larv; ++v) { int tv = v; if(a[j][i][0]) tv += a[j][i][1]; for(int x = 1; x < k; ++x) { int ts = dp[r][j][v+300][x]; if(ts == 0x80808080) continue; if(!a[j][i][0]) ts += a[j][i][1]; int tj = j+tv; tj = min(tj, n); if(tj <= 2) { lv = min(lv, 0); rv = max(rv, 0); upd(dp[tr][1][300][0], ts); if(tj < 1) continue; } if(x == k-1) continue; if(tj > 1) { lv = min(lv, tv); rv = max(rv, tv); upd(dp[tr][tj][tv+300][x+1], ts); } if(tj > 2) { lv = min(lv, tv-1); rv = max(rv, tv-1); upd(dp[tr][min(n,j+tv-1)][tv-1+300][x+1], ts); } if(n > 1) { lv = min(lv, tv+1); rv = max(rv, tv+1); upd(dp[tr][min(n,tj+1)][tv+1+300][x+1], ts); } } } } lalv = lv; larv = rv; lv = 300; rv = -300; memset(dp[r][0][0], 0x80, sizeof dp[r]); // 滚动数组要清空! } cout << dp[m&1][1][300][0]+(a[1][m][0]?0:a[1][m][1]) << '\n'; return 0; }
- 1
信息
- ID
- 1845
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者