CodeForces - 429B Working out(dp)

题目链接

看到题目,没什么思路

看了大佬博客:https://blog.csdn.net/xiaolonggezte/article/details/69145427,豁然开朗,还是有些小问题没注意,wa了挺久

题意:

    在n*m的格子里,A从(1,1)到(n,m),B从(n,1)到(1,m),

    A只能从 (i, j) 到 (i+1 , j) 或者 (i, j+1),B只能从 (i, j) 到 (i-1, j) 或者 (i, j+1)

    A和B的路线有且只有一点重合,并且这一点不在A和B的起点或终点,

    求怎样走使A和B的路线的权值之和(重合点的权值不计算)最大

思路:

    把路线分成四段,设重合点为x,计算 (1,1)到x,(n,m)到x,(1,m)到x,(n,1)到x 四段路的权值和;

注意:

    重合的点不在边界,并且只有一个点重合!

 

#include <iostream> 
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;

ll dp1[1100][1100],dp2[1100][1100],dp3[1100][1100],dp4[1100][1100];
//重合的点为x,dp1:(1,1)到x,dp2:(n,m)到x,dp3:(n,1)到x,dp4: (1,m)到x
ll a[1100][1100];

int main()
{
	memset(dp1,0,sizeof(dp1));
	memset(dp2,0,sizeof(dp2));
	memset(dp3,0,sizeof(dp3));
	memset(dp4,0,sizeof(dp4));
    int n,m;
	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++)
		    dp1[i][j] = max(dp1[i-1][j],dp1[i][j-1])+a[i][j];
	for(int i = n;i > 0;i--)
	    for(int j = m;j > 0;j--)
		    dp2[i][j] = max(dp2[i+1][j],dp2[i][j+1])+a[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])+a[i][j];
	for(int i = 1;i <= n;i++)
	    for(int j = m;j > 0;j--)
		    dp4[i][j] = max(dp4[i-1][j],dp4[i][j+1])+a[i][j];

    ll ans = 0;
    //注意(i,j)不在边界 
    for(int i  = 2; i < n; i ++)
        for(int j = 2; j < m; j ++)
        {
        	//除了(i,j)外的点不能再重合,所以一共就两种走法 ,没考虑路径,直接用和-4*a[i][j],wa疯 
            ans = max(ans,dp1[i - 1][j] + dp2[i + 1][j]+dp3[i][j - 1] + dp4[i][j + 1]);
            ans = max(ans,dp1[i][j - 1] + dp2[i][j + 1] + dp3[i + 1][j] + dp4[i - 1][j]);
        }
	cout<<ans<<endl;        					 
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值