Cf 429B [Working out]

Cf 429B Working out

题意:

给定一个 nm 列的矩阵 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);
}
posted @ 2022-12-25 21:58  zxr000  阅读(20)  评论(0编辑  收藏  举报