P1006 [NOIP2008 提高组] 传纸条
p1006
这道题其实和1004的方格取数差不多。
先放一下四维DP的代码,与之前不同,l从j + 1开始,这样保证了不会有重复的点,中点(n,m)的值为0,所以最后的答案是f[n][m - 1][n - 1][m]。
#include <bits/stdc++.h> using namespace std; int n, m, a[52][52], f[52][52][52][52]; int main() { cin >> n >> m; for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) cin >> a[i][j]; for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) for (int k = 1; k <= n; k ++) for (int l = j + 1; l <= m; l ++) f[i][j][k][l] = max(max(f[i][j - 1][k - 1][l], f[i - 1][j][k][l - 1]), max(f[i][j - 1][k][l - 1], f[i - 1][j][k - 1][l])) + a[i][j] + a[k][l]; cout << f[n][m - 1][n - 1][m] << '\n'; return 0; }
优化为三维DP,主要是基于这么一个性质:i+j=k+l=step,因为只能向下或者向右走,那么从起点到终点两条路径的长度肯定是一样的,我们可以在第一维枚举step,再枚举两条路径的横/纵坐标,知道了横/纵坐标,通过step可以得到纵/横坐标,这样只需要枚举三维即可,需要去掉重复的。
注意第一维的空间要开大一倍。
(三维比四维快了不止一点......)
#include <bits/stdc++.h> using namespace std; const int N = 52; int n, m, a[N][N], f[N << 1][N][N]; int main() { cin >> n >> m; for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) cin >> a[i][j]; for (int k = 1; k <= n + m - 1; k ++) for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++) { if (k - i + 1 < 1 || k - j + 1 < 1) continue;//纵坐标不合法 f[k][i][j] = max(max(f[k - 1][i][j], f[k - 1][i - 1][j - 1]), max(f[k - 1][i][j - 1], f[k - 1][i - 1][j])) + a[i][k - i + 1] + a[j][k - j + 1]; if (i == j) f[k][i][j] -= a[i][k - i + 1]; } cout << f[n + m - 1][n][n] << '\n'; return 0; }
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现