Codeforces 429B. Working out

题目链接:http://codeforces.com/problemset/problem/429/B

题意:给了一个nxm的矩阵,A从(1,1)出发,每次只能走相邻的右边或者下边的格子走到(n,m)停止.B从(n,1)出发,每次只能走相邻的右边或者上边的格子,走到(1,m)停止,两人的路线只能交于一个格子,除相交的格子外,求两人路线上其他格子总和的最大值

分析:动态规划.通过递推求出分别以左上角,左下角,右上角,右下角为出发点到每一个个格子的距离和的最大值.注意右上角和右下角分别和左下角,左上角对应,是一个逆过程.还有一个坑点就是边界没有意义,要赋予极小值.我们枚举每个格子的上下左右对应的两种可能情况(注意不能是到某个格子的距离和再减去该格子的四倍,因为这样有可能两个人的路线相交)

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1010;
int mp[maxn][maxn];
ll dp1[maxn][maxn],dp2[maxn][maxn],dp3[maxn][maxn],dp4[maxn][maxn];
//dp1 left up dp2 left down dp3 right up dp4 right down
const int INF = 0x3f3f3f3f;
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            scanf("%d",&mp[i][j]);
        }
    }
    for(int i = 1; i <= m; i++)
        dp1[1][i] = dp1[1][i - 1] + mp[1][i];
    for(int i = 2; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(j == 1)dp1[i][j] = dp1[i - 1][j] + mp[i][j];
            else dp1[i][j] = max(dp1[i - 1][j],dp1[i][j - 1]) + mp[i][j];
        }
    }
    for(int i = 1; i <= m; i++)
        dp2[n][i] = dp2[n][i - 1] + mp[n][i];
    for(int i = n - 1; i >= 1; i--)
    {
        for(int j = 1; j <= m; j++)
        {
            if(j == 1)dp2[i][j] = dp2[i + 1][j] + mp[i][j];
            else dp2[i][j] = max(dp2[i + 1][j],dp2[i][j - 1])+ mp[i][j];
        }
    }
    for(int i = m; i >= 1; i--)
        dp3[1][i] = dp3[1][i + 1] + mp[1][i];
    for(int i = 2; i <= n; i++)
    {
        for(int j = m; j >= 1; j--)
        {
            if(j == m)dp3[i][j] = dp3[i - 1][j] + mp[i][j];
            else dp3[i][j] = max(dp3[i - 1][j],dp3[i][j + 1]) + mp[i][j];
        }
    }
    for(int i = m; i >= 1; i--)
        dp4[n][i] = dp4[n][i + 1] + mp[n][i];
    for(int i = n - 1; i >= 1; i--)
    {
        for(int j = m; j >= 1; j--)
        {
            if(j == m)dp4[i][j] = dp4[i + 1][j] + mp[i][j];
            else dp4[i][j] = max(dp4[i + 1][j],dp4[i][j + 1]) + mp[i][j];
        }
    }
    ll maxx = 0;
//    for(int i = 1; i <= n; i++)
//    {
//        for(int j = 1; j <= m; j++)
//        {
//            printf("%lld,%lld,%lld,%lld\n",dp1[i][j],dp2[i][j],dp3[i][j],dp4[i][j]);
//        }
//    }
    for(int i = 1; i <= n; i++)
    {
        dp1[i][0] = dp2[i][0] = dp3[i][0] = dp4[i][0] = -INF;
        dp1[i][m + 1] = dp2[i][m + 1] = dp3[i][m + 1] = dp4[i][m + 1] = -INF;
    }
    for(int i = 1; i <= m; i++)
    {
        dp1[0][i] = dp2[0][i] = dp3[0][i] = dp4[0][i] = -INF;
        dp1[n + 1][i] = dp2[n + 1][i] = dp3[n + 1][i] = dp4[n + 1][i] = -INF;
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            ll ans = dp1[i][j - 1]+dp2[i + 1][j]+dp3[i - 1][j]+dp4[i][j + 1];
            maxx = max(maxx,ans);
            ans = dp1[i - 1][j] + dp2[i][j - 1] + dp3[i][j + 1] + dp4[i + 1][j];
            maxx = max(maxx,ans);
        }
    }
    cout<<maxx<<endl;
    return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值