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;
}

image



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   YHXo  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示