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;
}

猜你喜欢

转载自blog.csdn.net/weixin_42754600/article/details/83927229