zoukankan      html  css  js  c++  java
  • 「EZEC-4.5」走方格

    题目链接

    Solution

    考虑对于每个格子,计算经过它的最长路是多少。从 ((1,1)) 开始正着 (mathrm{dp}) 一遍,得到数组 (mathrm{f1[][]}),再从 (mathrm{(n,m)}) 开始反着 (mathrm{dp}) 一遍,得到数组 (mathrm{f2[][]})

    对于 (mathrm{(i,j)}),经过它的最长路 (dis_{i,j}=f1_{i,j}+f2_{i,j}-a_{i,j})(a_{i,j}) 重复计算)

    由于只能向下或向右走,通过观察(口胡),可以发现一个性质:每个与 ((1,1))曼哈顿距离只会走 (1) 次。换成人话,就是每个左下-右上的对角线将会被经过恰好一次。同一条对角线上的点满足 (i + j) 相等。

    这样我们考虑维护条对角线上 经过每个点最大价值 的最大值((mathrm{maxx}))和次大值((mathrm{sec}))。那么枚举 (mathrm{(i,j)}) 点被置成 (0) 之后的最大价值是:

    [max left{ sec_{i+j}, f1_{i,j} + f2_{i,j} - 2 imes a_{i,j} } ight. ]

    [(如果 mathrm{dis_{i,j}} 是该对角线的最大值) ]

    [max left{ maxx_{i+j}, f1_{i,j} + f2_{i,j} - 2 imes a_{i,j} } ight. ]

    [(如果 mathrm{dis_{i,j}} 不是该对角线的最大值) ]

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    
    const int N = 2333;
    LL n, m, Ans = 1e18;
    LL idx[N << 4], idy[N << 4], a[N][N], f1[N][N], f2[N][N], maxx[N << 4], sec[N << 4];
    
    signed main()
    {
        scanf("%lld%lld", &n, &m);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                scanf("%lld", &a[i][j]);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                f1[i][j] = max(f1[i - 1][j] + a[i][j], f1[i][j - 1] + a[i][j]);
        for(int i = n; i >= 1; i--)
            for(int j = m; j >= 1; j--)
                f2[i][j] = max(f2[i + 1][j] + a[i][j], f2[i][j + 1] + a[i][j]);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
            {
                LL res = f1[i][j] + f2[i][j] - a[i][j];
                if(res > maxx[i + j])
                {
                    sec[i + j] = maxx[i + j];
                    maxx[i + j] = res;
                    idx[i + j] = i, idy[i + j] = j;
                }
                else sec[i + j] = max(sec[i + j], res);
            }
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
            {
                if(idx[i + j] == i && idy[i + j] == j)
                    Ans = min(Ans, max(sec[i + j], f1[i][j] + f2[i][j] - 2 * a[i][j]));
                else Ans = min(Ans, max(maxx[i + j], f1[i][j] + f2[i][j] - 2 * a[i][j]));
            }
        printf("%lld", Ans);
        return 0;
    }
    
  • 相关阅读:
    C++调用外部应用程序
    SVN文件加锁
    vs ComboBox显示多行
    __slots__ Python Class限制添加属性
    Python数据分析之pandas学习
    整理Lua和Unity和Lua交互文章链接
    [整理]Unity3D游戏开发之Lua
    ping telnet ssh netstat
    java rpc
    css 手机适配
  • 原文地址:https://www.cnblogs.com/Andy-park/p/13771783.html
Copyright © 2011-2022 走看看