Cf 429B Working out
题意:
给定一个 n 行 m 列的矩阵 A,在该矩阵中找出两条路径,要求:
- 第一条路径从矩阵左上角 (1, 1) 走到矩阵右下角 (n, m),每次只能向下或向右走。
- 第二条路径从矩阵左下角 (n, 1) 走到矩阵右上角 (1, m),每次只能向上或向右走。
- 两条路径有且仅有一个交点。
找出两条路径,在满足上述要求的情况下,使得路径经过的点除交点外的权值之和尽量大,输出这一最大值。
数据范围:
\(3 \le n,m\le 1000\)
思路:
首先因为两个路径有且仅有一个交点,所以可以肯定,两条路径一定不会在网格的最外层相遇。
所以直接枚举剩下的相遇点取最优解即可。
dp
预处理出从左上角和右下角,左下角和右上角到达 \((i,j)\) 四个方格 \((i - 1,j),(i + 1,j)(i,j - 1),(i,j + 1)\)最大值
实现:
#include <stdio.h>
#include <algorithm>
using namespace std;
long long grid[1005][1005];
long long dp1[1005][1005]; //(1,1)->(n,m)
long long dp2[1005][1005]; //(1,m)->(n,1)
long long dp3[1005][1005]; //(n,1)->(1,m)
long long dp4[1005][1005]; //(n,m)->(1,1)
int main()
{
long long n, m;
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%lld", &grid[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
//右上
dp1[i][j] = max(dp1[i - 1][j], dp1[i][j - 1]) + grid[i][j];
}
for (int i = 1; i <= n; i++)
for (int j = m; j > 0; j--)
{
//右下
dp2[i][j] = max(dp2[i - 1][j], dp2[i][j + 1]) + grid[i][j];
}
for (int i = n; i > 0; i--)
for (int j = 1; j <= m; j++)
{
//左上
dp3[i][j] = max(dp3[i + 1][j], dp3[i][j - 1]) + grid[i][j];
}
for (int i = n; i > 0; i--)
for (int j = m; j > 0; j--)
{
//左下
dp4[i][j] = max(dp4[i + 1][j], dp4[i][j + 1]) + grid[i][j];
}
long long res = 0;
for (int i = 2; i < n; i++)
for (int j = 2; j < m; j++)
{
res = max(res, dp1[i - 1][j] + dp4[i + 1][j] + dp2[i][j + 1] + dp3[i][j - 1]);
res = max(res, dp1[i][j - 1] + dp4[i][j + 1] + dp2[i - 1][j] + dp3[i + 1][j]);
}
printf("%lld\n", res);
}
标签:dp4,dp2,Working,int,res,Cf,long,1005,out
From: https://www.cnblogs.com/zxr000/p/17004689.html